Articles

Adam l’automate

Lorsque vous commencerez à écrire des scripts PowerShell, vous arriverez inévitablement à un endroit où vous devrez traiter plusieurs éléments d’une collection. C’est alors que vous devrez creuser dans les boucles foreach de PowerShell et apprendre ce qu’elles sont.

Presque tous les langages de programmation ont une construction appelée boucles ; PowerShell n’est pas différent. L’un des types de boucles les plus populaires dans PowerShell est la boucle foreach. À sa base, une boucle foreach lit une collection entière d’éléments et foreach item, exécute une sorte de code.

L’un des aspects les plus déroutants de la boucle foreach de PowerShell pour les débutants est toutes les options dont vous disposez. Il n’y a pas qu’une seule façon de traiter chaque élément d’une collection ; il y en a trois !

Dans cet article, vous allez apprendre comment fonctionne chaque type de boucle foreach et quand utiliser l’un plutôt que l’autre. Lorsque vous en aurez terminé avec cet article, vous aurez une bonne compréhension de chaque type de boucle foreach.

Table des matières

Bases de la boucle ForEach de PowerShell

L’un des types de boucles les plus courants que vous utiliserez dans PowerShell est le type de boucle foreach. Une boucle foreach lit un ensemble d’objets (itère) et se termine lorsqu’elle a terminé avec le dernier. La collection d’objets lus est généralement représentée par un tableau ou une table de hachage.

NOTE : Le terme itération est un terme de programmation qui fait référence à chaque exécution d’une boucle. Chaque fois qu’une boucle complète un cycle, cela s’appelle une itération. Le fait d’exécuter une boucle sur un ensemble d’objets est communément appelé itération sur l’ensemble.

Parfois, vous devez créer un fichier texte à travers certains dossiers répartis sur un système de fichiers. Disons que les chemins des dossiers sont C:\FolderC:\Program Files\Folder2 et C:\Folder3. Sans boucle, nous devrions référencer la cmdlet Add-Content trois fois.

Add-Content -Path 'C:\Folder\textfile.txt' -Value 'This is the content of the file'Add-Content -Path 'C:\Program Files\Folder2\textfile.txt' -Value 'This is the content of the file'Add-Content -Path 'C:\Folder2\textfile.txt' -Value 'This is the content of the file'

Quelle est la seule différence entre chacune de ces références de commande ? Il s’agit de la valeur Path. La valeur de Path est la seule valeur qui change parmi chacune d’elles.

Vous dupliquez beaucoup de code. Vous perdez du temps à taper et vous vous ouvrez à des problèmes sur la route. Au lieu de cela, vous devriez créer un « ensemble » qui inclut juste tous les éléments qui changent. Pour cet exemple, nous allons utiliser un tableau.

$folders = @('C:\Folder','C:\Program Files\Folder2','C:\Folder3')

Vous avez maintenant chacun de ces chemins stockés dans un seul « ensemble » ou tableau. Vous êtes maintenant prêt à utiliser une boucle pour itérer sur chacun de ces éléments. Avant de le faire, cependant, c’est le bon moment pour mentionner un sujet qui fait généralement trébucher les nouveaux venus dans PowerShell. Contrairement aux autres types de boucles, les boucles foreach ne sont pas une seule et même chose.

Il existe techniquement trois types de boucles foreach dans PowerShell. Bien que chacune soit similaire à utiliser, il est important de comprendre la différence.

L’instruction foreach

Le premier type de boucle foreach est une instruction. foreach est un mot-clé interne à PowerShell qui n’est ni un cmdlet ni une fonction. L’instruction foreach est toujours utilisée dans le formulaire : foreach ($i in $array).

En utilisant l’exemple ci-dessus, la variable $i représente l’itérateur ou la valeur de chaque élément dans $path car elle itère sur chaque élément du tableau.

Notez que la variable iterator n’a pas besoin d’être $i. Le nom de la variable peut être n’importe quoi.

Dans l’exemple ci-dessous, vous pouvez accomplir la même tâche que la répétition de la référence Add-Content en faisant ceci :

# Create an array of folders$folders = @('C:\Folder','C:\Program Files\Folder2','C:\Folder3')# Perform iteration to create the same file in each folderforeach ($i in $folders) { Add-Content -Path "$i\SampleFile.txt" -Value "This is the content of the file"}

L’instruction foreach est connue pour être une alternative plus rapide que l’utilisation du cmdlet ForEach-Object.

Le cmdlet ForEach-Object

Si foreach est une déclaration et ne peut être utilisée que d’une seule manière, ForEach-Object est un cmdlet avec des paramètres qui peuvent être employés de nombreuses manières différentes. Comme l’instruction foreach, la cmdlet ForEach-Object peut itérer sur un ensemble d’objets. Seulement cette fois, il passe cet ensemble d’objets et l’action à effectuer sur chaque objet en tant que paramètre, comme indiqué ci-dessous.

$folders = @('C:\Folder','C:\Program Files\Folder2','C:\Folder3')$folders | ForEach-Object (Add-Content -Path "$_\SampleFile.txt" -Value "This is the content of the file")

Note : Pour rendre les choses plus confuses, la ForEach-Object cmdlet a un alias appelé foreach. Selon la façon dont le terme « foreach » est appelé, l’instruction foreach est exécutée, ou la ForEach-Object s’exécute.

Une bonne façon de différencier ces situations est de remarquer si le terme « foreach » est suivi de ($someVariable in $someSet). Sinon, dans tout autre contexte, l’auteur du code utilise probablement l’alias de ForEach-Object.

La méthode foreach()

L’une des plus récentes foreach boucles a été introduite dans PowerShell v4 appelée méthode foreach(). Cette méthode existe sur un tableau ou un objet de collection. La méthode foreach() possède un paramètre de bloc de script standard qui contient les actions à entreprendre à chaque itération, tout comme les autres.

$folders = @('C:\Folder','C:\Program Files\Folder2','C:\Folder3')$folders.ForEach({Add-Content -Path "$_\SampleFile.txt" -Value "This is the content of the file"})

La différence la plus significative avec la méthode foreach() est son fonctionnement sous le capot.

L’utilisation de la méthode foreach() est considérablement plus rapide et l’est sensiblement sur de grands ensembles. Il est recommandé d’utiliser cette méthode plutôt que les deux autres si possible.

Mini-projet : Boucle sur un ensemble de noms de serveurs

L’une des utilisations les plus courantes d’une boucle dans PowerShell consiste à lire un ensemble de serveurs à partir d’une source quelconque et à effectuer une action sur chacun d’eux. Pour notre premier mini-projet, construisons un code qui nous permettra de lire des noms de serveurs (un par ligne) à partir d’un fichier texte et d’effectuer un ping sur chaque serveur pour déterminer s’il est en ligne ou non.

Liste de noms de serveurs dans un fichier texte
Liste de noms de serveurs dans un fichier texte

Pour ce flux de travail, quel type de boucle pensez-vous fonctionnerait le mieux ?

Vous avez remarqué que j’ai mentionné le mot  » set  » comme dans  » set of servers « . C’est un indice juste là. Vous avez déjà un nombre spécifié de noms de serveurs, et vous aimeriez effectuer une action sur chacun d’eux. Cela semble être une excellente occasion d’essayer la boucle PowerShell la plus couramment utilisée ; la boucle foreach.

La première tâche consiste à créer un ensemble de noms de serveurs dans le code. La façon la plus courante de le faire est de créer un tableau. Heureusement pour nous que Get-Content, par défaut, renvoie un tableau dont chaque élément est représenté par une seule ligne dans le fichier texte.

Premièrement, créez un tableau de tous mes noms de serveurs et appelez-le $servers.

$servers = Get-Content .\servers.txt

Maintenant que vous avez créé le tableau, vous allez devoir confirmer si chaque serveur est en ligne ou non. Un excellent cmdlet pour tester la connexion d’un serveur s’appelle Test-Connection. Cette cmdlet effectue quelques tests de connexion sur un ordinateur pour voir s’il est en ligne ou non.

En exécutant Test-Connection à l’intérieur d’une boucle foreach pour lire chaque ligne de fichier, vous pouvez passer chaque nom de serveur représenté par la variable $serverTest-Connection. Voilà comment PowerShell peut boucler un fichier texte. Vous pouvez voir un exemple de ce fonctionnement ci-dessous.

foreach ($server in $servers) {try {$null = Test-Connection -ComputerName $server -Count 1 -ErrorAction STOPWrite-Output "$server - OK"}catch {Write-Output "$server - $($_.Exception.Message)"}}

Lorsque la boucle foreach est exécutée, elle ressemblera alors à quelque chose comme ceci :

La boucle de test de connexion à travers une liste de noms de serveurs
La boucle de test de connexion à travers une liste de noms de serveurs

.Connexion à travers une liste de noms de serveurs

Vous avez maintenant testé avec succès la connexion d’un fichier texte rempli de noms de serveurs ! À ce stade, vous pouvez maintenant ajouter ou supprimer des noms de serveurs à l’intérieur du fichier texte à volonté sans modifier le code.

Vous avez pratiqué avec succès ce que nous avons prêché, la méthode DRY.

ForEach Exemples PowerShell

Regardons quelques exemples d’utilisation de la boucle ForEach. Ceux-ci sont basés sur des cas d’utilisation réels montrant le concept que vous pouvez modifier pour l’adapter à vos besoins.

Exemple 1 : Création d’un fichier dans chaque sous-dossier d’un répertoire à l’aide de l’instruction ForEach

Cet exemple démontre l’utilisation courante de PowerShell foreach folder dans un répertoire.

Supposons qu’il existe dix sous-dossiers à l’intérieur du dossier C:\ARCHIVE_VOLUMES. Chaque sous-dossier représente un volume d’archives qui est sauvegardé quotidiennement. Une fois chaque sauvegarde terminée, un fichier nommé BackupState.txt est créé à l’intérieur de chaque dossier contenant la date à laquelle il a été sauvegardé.

Vous pouvez voir un exemple de ce à quoi cela pourrait ressembler ci-dessous.

Sous-répertoires sous C:\ARCHIVE_VOLUMES
Sous-répertoires sous C :\ARCHIVE_VOLUMES

Le script ci-dessous effectue trois actions :

  • obtient la liste de tous les sous-dossiers à l’intérieur de C:\ARCHIVE_VOLUMES
  • Les boucles à travers chaque dossier

  • créent un fichier texte nommé BackupState.txt contenant la date et l’heure actuelles sa valeur

L’exemple ci-dessous utilise l’instruction foreach.

# Define the TOP-level folder$TOP_FOLDER = "C:\ARCHIVE_VOLUMES"# Get all sub folders recursively$Child_Folders = Get-ChildItem -Path $TOP_FOLDER -Recurse | Where-Object { $_.PSIsContainer -eq $true }# Create a text file in each sub-folder and add the current date/time as value.foreach ($foldername in $Child_Folders.FullName) { (get-date -Format G) | Out-File -FilePath "$($foldername)\BackupState.txt" -Force}

En utilisant la cmdlet Get-ChildItem, vous pouvez confirmer que les fichiers ont été créés ou mis à jour à l’intérieur de chacun des sous-dossiers.

Get-ChildItem -Recurse -Path C:\ARCHIVE_VOLUMES -Include backupstate.txt | Select-Object Fullname,CreationTime,LastWriteTime,Length

La capture d’écran ci-dessous montre la sortie du script affichant tous les BackupState.txt fichiers trouvés dans chaque sous-répertoire.

Un fichier texte est créé dans chaque sous-répertoire
Un fichier texte est créé dans chaque sous-répertoire

Exemple 2 : Lecture du contenu de chaque fichier texte dans les sous-répertoires

Puis, pour démontrer l’utilisation du fichier foreach de PowerShell dans un répertoire, le script ci-dessous va lire chaque BackupState.txt fichier créé dans l’exemple 1.

  • Trouver récursivement tous les BackupState.txt fichiers à l’intérieur de chaque sous-répertoire.
  • Utilisant l’instruction foreach, lisez chaque fichier texte pour obtenir la valeur « last backup time ».
  • Affichez le résultat à l’écran.
## Find all BackupState.txt files in C:\ARCHIVE_VOLUMES$files = Get-ChildItem -Recurse -Path C:\ARCHIVE_VOLUMES -Include 'BackupState.txt' | Select-Object DirectoryName,FullName## Read the contents of each fileforeach ($file in $files) { Write-Output ("$($file.DirectoryName) last backup time - " + (Get-Content $file.FullName))}

Une fois le script exécuté dans votre session PowerShell, vous devriez voir une sortie similaire à la capture d’écran ci-dessous. Cela montre que PowerShell boucle dans les fichiers, lit le contenu et affiche la sortie.

Utilisation de foreach pour boucler dans les fichiers et lire son contenu.
Utilisation de foreach pour boucler dans les fichiers et lire son contenu.

Exemple 3 : Obtenir des services et les démarrer à l’aide du CmdLet ForEach-Object

Les administrateurs système ont souvent besoin d’obtenir l’état des services et de déclencher un workflow manuel ou automatique pour remédier à tout service défaillant. Examinons l’exemple de script utilisant le ForEach-Object cmdlet.

Pour cet exemple, le script ci-dessous fera ce qui suit :

  • Obtenir une liste des services qui sont configurés pour un démarrage automatique mais qui ne sont actuellement pas dans un état d’exécution.
  • Puis, les éléments de la liste sont acheminés vers le cmdlet ForEach-Object pour tenter de démarrer chaque service.
  • Un message de réussite ou d’échec s’affiche en fonction du résultat de la Start-Service commande.
## Get a list of automatic services that are stopped.$services = Get-Service | Where-Object {$.StartType -eq 'Automatic' -and $.Status -ne 'Running'}## Pass each service object to the pipeline and process them with the Foreach-Object cmdlet$services | ForEach-Object { try { Write-Host "Attempting to start '$($.DisplayName)'" Start-Service -Name $.Name -ErrorAction STOP Write-Host "SUCCESS: '$($.DisplayName)' has been started" } catch { Write-output "FAILED: $($.exception.message)" }}

Lorsque le script est exécuté, il ressemble à la capture d’écran de sortie ci-dessous. Comme vous pouvez le voir, chaque service a reçu une commande de démarrage. Certains ont été lancés avec succès tandis que d’autres n’ont pas réussi à démarrer.

Utilisation de la boucle ForEach-Object pour démarrer les services
Utilisation de la boucle ForEach-Object pour démarrer les services

Exemple 4 : Lecture des données d’un CSV à l’aide de la méthode ForEach()

L’utilisation des données des fichiers CSV est populaire parmi les administrateurs système. Mettre des enregistrements à l’intérieur d’un fichier CSV facilite l’exécution d’opérations en masse en utilisant la combinaison Import-CSV et ForEach. Cette combinaison est couramment utilisée pour créer plusieurs utilisateurs dans Active Directory.

Dans cet exemple suivant, on suppose que vous disposez d’un fichier CSV avec deux colonnes – Prénom et Nom. Ce fichier CSV doit ensuite être alimenté avec les noms des nouveaux utilisateurs à créer. Le fichier CSV ressemblerait à quelque chose comme ci-dessous.

"Firstname","Lastname""Grimm","Reaper""Hell","Boy""Rick","Rude"

Maintenant pour le bloc de script suivant. Tout d’abord, importez le fichier CSV en passant le chemin du contenu à la cmdlet Import-CSV. Ensuite, en utilisant la méthode foreach(), bouclez à travers les noms et créez les nouveaux utilisateurs dans Active Directory.

# Import list of Firstname and Lastname from CSV file$newUsers = Import-Csv -Path .\Employees.csvAdd-Type -AssemblyName System.Web# Process the list$newUsers.foreach( { # Generate a random password $password = ::GeneratePassword((Get-Random -Minimum 20 -Maximum 32), 3) $secPw = ConvertTo-SecureString -String $password -AsPlainText -Force # Formulate a username $userName = '{0}{1}' -f $_.FirstName.Substring(0, 1), $_.LastName # Build new user attributes $NewUserParameters = @{ GivenName = $_.FirstName Surname = $_.LastName Name = $userName AccountPassword = $secPw } try { New-AdUser @NewUserParameters -ErrorAction Stop Write-Output "User '$($userName)' has been created." } catch { Write-Output $_.Exception.Message } })

Lors de l’exécution, vous devriez maintenant avoir créé un utilisateur AD pour chaque ligne du fichier CSV !

Résumé

La logique derrière la boucle foreach dans PowerShell n’est pas différente de celle des autres langages de programmation. Elle change seulement en fonction de la façon dont elle est utilisée et de la variante de la boucle foreach choisie pour une tâche spécifique.

Dans cet article, vous avez appris les différents types de boucles foreach disponibles dans PowerShell, et ce qu’il faut prendre en compte pour choisir celle à utiliser. Vous avez également vu les trois types de boucles foreach en action à l’aide de différents exemples de scénarios.

Lecture complémentaire

  • Gestion des fichiers CSV dans PowerShell avec Import-Csv (boucle foreach)
  • New-ADUser : créer des utilisateurs Active Directory avec PowerShell
  • Bases de la boucle PowerShell : Foreach | Scripting Blog

.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *