Windows PowerShellConstructions de Windows PowerShell

Don Jones

Le mois dernier, je vous ai montré de quelle manière utiliser immédiatement Windows PowerShell afin d'effectuer certaines tâches d'administration sans pour autant devoir effectivement écrire des scripts. Toutefois, même si Windows PowerShell est un excellent shell interactif, vous tirerez réellement parti de ses fonctions et pourrez automatiser des tâches plus complexes en commençant à utiliser son langage de script puissant et simple à la fois.

Néanmoins, vous pouvez vous poser une question : Microsoft a réellement besoin d'un autre langage de script ? Après tout, Microsoft nous a déjà fourni KiXtart (un processeur de scripts de connexion) et VBScript (Visual Basic® Scripting Edition). La réponse est quand même oui. Microsoft avait réellement besoin d'un autre langage de script. Je vais vous en exposer la raison.

Le langage Windows PowerShell™ se devait d'être simple et intuitif afin que les administrateurs puissent le maîtriser sans suivre de trop longues formations. Il se devait également d'être relativement souple afin de s'adapter à l'ensemble des fonctionnalités puissantes que Windows PowerShell lui-même propose aux utilisateurs.

Windows PowerShell étant basé sur Microsoft® .NET Framework, sa syntaxe de script devait être aisément adaptable à .NET. Lors de la création d'un langage de script pour Windows PowerShell, les concepteurs ont choisi une syntaxe qui correspond essentiellement à un langage C# très simplifié (prononcé C-Sharp, l'un des langages fournis avec .NET Framework) . Pourquoi ne pas s'inspirer d'une syntaxe de type VBScript ? Le langage de script Windows PowerShell n'est en fait pas tellement différent de VBScript, mais en s'approchant davantage de la syntaxe C#, PowerShell propose une sorte de base initiale pour l'apprentissage de la programmation .NET Framework. Si vous décidez un jour de passer à Visual Studio® et de commencer à écrire des applications C#, la majeure partie de votre syntaxe de script Windows PowerShell pourra vous servir en ce sens.

Dans ce contexte, les constructions sont l'une des choses les plus importantes dans le langage de script Windows PowerShell (ou dans tout autre langage de script). Il s'agit d'éléments de langage spéciaux permettant à Windows PowerShell d'effectuer des comparaisons logiques pour entreprendre diverses actions en fonctions des résultats ou pour permettre de répéter indéfiniment une ou plusieurs instructions.

Penser logique

Les comparaisons logiques sont au cœur de bon nombre de constructions de langage de script ; Windows PowerShell n'y fait pas exception. Globalement, une comparaison analyse deux valeurs ou deux objets et détermine si le résultat est True (vrai) ou False (faux). Par exemple, vous pouvez vous demander si la date d'expiration du mot de passe utilisateur est identique à la date du jour. Le résultat sera True (vrai) si ces dates correspondent ou False (faux) si elles diffèrent. Remarquez que j'utilise les termes avec majuscules pour True (vrai) et False (faux) ; en effet, ils ont une signification spéciale dans Windows PowerShell.

Voici un exemple d'une comparaison logique réelle dans Windows PowerShell :

PS C:\> $a = 1
PS C:\> $b = 2
PS C:\> $a -eq $b
False

J'ai créé une variable nommée $a et l'ai définie pour qu'elle contienne la valeur 1. Dans Windows PowerShell, les noms de variable commencent toujours par un signe dollar afin de les reconnaître plus facilement. Techniquement, le signe = fait référence à l'opérateur d'attribution ; en effet, il sert à attribuer une valeur. Ensuite, j'ai créé une deuxième variable nommée $b à laquelle j'ai attribué la valeur 2. Vient ensuite la comparaison logique : je demande à Windows PowerShell de comparer les contenus de $a et $b à l'aide de l'opérateur -eq (égalité). PowerShell effectue la comparaison, détermine que ces deux variables ne sont pas égales, puis affiche le résultat : False.

Les opérateurs Windows PowerShell sont légèrement différents de ceux des autres langage de script, ainsi que de ceux de C#. La plupart des langages utilisent l'opérateur = aussi bien pour effectuer des vérifications d'égalité que des attributions de valeurs ; Windows PowerShell évite toute confusion en dédiant un opérateur à chaque fonction. La figure 1 illustre les opérateurs de comparaison Windows PowerShell avec leurs équivalents dans d'autres langages (tels que VBScript) qui vous sont peut-être déjà familiers.

Figure 1 Opérateurs de comparaison PowerShell

Opérateur Nom Description
-eq Egalité Teste les valeurs pour déterminer si elles sont égales. D'autres langages peuvent utiliser = ou == pour tester l'égalité.
-ne Non égal Teste les valeurs pour déterminer si elles sont inégales. D'autres langages peuvent utiliser <> ou != pour tester l'inégalité.
*-gt Supérieur à Teste une valeur pour déterminer si elle est supérieure à une autre. D'autres langages peuvent utiliser le caractère >.
-lt Inférieur à Teste une valeur pour déterminer si elle est inférieure à une autre. D'autres langages peuvent utiliser le caractère <.
-ge Supérieur ou égal à Teste une valeur pour déterminer si elle est supérieure ou égale à une autre. Identique à >= dans VBScript et les autres langages.
-le Inférieur ou égal à Teste une valeur pour déterminer si elle est inférieure ou égale à une autre. Identique à <= dans VBScript et les autres langages.

Ces opérateurs de comparaison comportent une autre fonction intéressante. Voyez plutôt la comparaison suivante :

PS C:\> $a = "TechNet"
PS C:\> $b = "technet"
PS C:\> $a -eq $b
True

Par défaut, les opérateurs de comparaison ne sont pas sensibles à la casse ; ainsi la version avec majuscules de TechNet est considérée comme équivalente à « technet ». Cette caractéristique s'avère pratique du fait que vous ne vous souciez généralement pas de la casse des lettres dans la plupart des tâches d'administration. Toutefois, il arrive que la casse vous soit utile ; vous pouvez alors demander à Windows PowerShell d'effectuer une comparaison sensible à la casse en ajoutant la lettre c à l'opérateur de comparaison :

PS C:\> $a -ceq $b
False

De la même manière, si vous êtes soucieux de savoir si Windows PowerShell effectue une comparaison sensible à la casse ou non, vous pouvez l'y forcer en ajoutant la lettre i :

PS C:\> $a -ieq $b
True

Gardez à l'esprit que les comparaisons logiques ont toujours l'une de ces deux valeurs pour résultat : True (vrai) ou False (faux).

Prendre des décisions

A présent que vous savez comment écrire des comparaisons logiques, vous pouvez les utiliser dans les constructions. La première construction que je vais vous présenter permet à Windows PowerShell de prendre des décisions fondées sur une comparaison. Il s'agit d'une construction en If (si), laquelle comporte quelques variantes. Voici la plus simple d'entre elles :

PS C:\> if ($a -eq $b) {
>> Write-Host "They are equal"
>> }
>>
They are equal

Cette section comporte des éléments intéressants à retenir. Tout d'abord, les variables $a et $b contiennent encore les valeurs « TechNet » et « technet », respectivement. J'ai commencé la construction en utilisant le mot-clé If (si). A sa suite, entre parenthèses, j'ai saisi la comparaison logique à effectuer. Vient ensuite une accolade, laquelle indique le début de ce que j'appelle le code conditionnel, c'est-à-dire le code que Windows PowerShell exécute si le résultat de la comparaison est True (vrai). Le premier exemple vous a démontré que le résultat de cette comparaison True (vrai) ; je m'attends donc à ce que le code conditionnel s'exécute. Je saisis mon code conditionnel, Write-Host "Elles sont égales", puis j'appuie sur la touche Entrée. Enfin, je termine la section du code conditionnel en entrant une accolade fermante et en appuyant sur la touche Entrée à deux reprises. (La deuxième frappe sur la touche Entrée sur une ligne vierge permet à l'analyseur de savoir que j'en ai terminé avec l'écriture et suis prêt à ce qu'il exécute le code.)

Notez que cette construction ne s'exécute pas depuis un fichier de script. Je l'ai simplement saisie dans la ligne de commandes Windows PowerShell. C'est ce qui rend Windows PowerShell unique dans le monde du script Windows : les scripts peuvent aussi bien être créés de manière interactive qu'intégrés dans un fichier pour un stockage permanent.

Dès que j'ai saisi l'accolade ouvrante et appuyé sur la touche Entrée, Windows PowerShell a affiché une invite >>. Cette invite revient à dire « Je reconnais que vous êtes dans une construction et je suis prêt à vous laisser saisir ce que bon vous semble au sein de cette dernière ». Dès que j'ai entré l'accolade fermante et frappé sur la touche Entrée à deux reprises, Windows PowerShell a immédiatement exécuté la construction, déterminé que le résultat de la comparaison logique était True (vrai) et exécuté le code conditionnel. Vous pouvez vous en rendre compte grâce à l'affichage de « Elles sont égales » avant que PowerShell ne retourne à son invite normale. L'utilisation de Windows PowerShell pour écrire des scripts de manière interactive vous permet de tester rapidement des morceaux de code avant de les assembler dans un script permanent, afin d'en simplifier l'apprentissage et le débogage.

Je dois signaler que Windows PowerShell n'est pas particulièrement pointilleux sur les actions telles que les pressions sur la touche Entrée. Ainsi, ce qui suit aura la même fonctionnalité que l'exemple précédent :

PS C:\> if ($a -eq $b) { Write-Host "They are equal" }
They are equal

Etant donné que j'ai tout saisi sur une même ligne, Windows PowerShell n'a pas eu besoin d'afficher l'invite spéciale >> ; il a simplement exécuté la construction jusqu'à ce que j'appuie sur Entrée à la fin de la ligne. Comment Windows PowerShell a-t-il su qu'il pouvait exécuter la construction ? Parce qu'à ce stade, elle était terminée, l'accolade fermante ayant été saisie.

Précédemment, j'ai fait allusion à d'autres variantes de la construction If (si). En voici un exemple complet, présenté tel qu'il pourrait apparaître dans un fichier de script PS1, plutôt que dans le shell :

if ($a -eq $b) {
  Write-Host "They are equal"
} elseif ($a -lt $b) {
  Write Host "One is less than the other"
} else {
  Write Host "One is greater than the other"
}

Cette construction commence de la même manière, à l'aide du mot-clé If (si). Néanmoins, dans l'éventualité d'un résultat False (faux) pour la comparaison, j'ai ajouté une autre comparaison à l'aide du mot-clé Elseif (autrement, si). Si cette deuxième comparaison est également False (faux), mon dernier mot-clé, Else (autrement), fournit un ensemble de code final à exécuter.

Se répéter

Windows PowerShell contient plusieurs constructions permettant de répéter indéfiniment l'exécution d'un code jusqu'à ce qu'une comparaison donne un résultat True (vrai) ou False (faux). Les programmeurs appellent cela des constructions en boucle. Mieux encore, l'une des constructions en boucle les plus utiles est capable d'énumérer les objets d'une collection et d'exécuter une ou plusieurs lignes de code pour chaque objet. Cette construction est fort justement appelée construction « Foreach » (littéralement, « pour chaque ») et se présente comme suit :

PS C:\> $names = get-content "c:\computers.txt"
PS C:\> foreach ($name in $names) {
>> Write-Host $name
>> }
>>
don-pc
testbed

J'ai commencé par demander à l'applet de commande Get-Content de Windows PowerShell d'extraire le contenu du fichier c:\computers.txt que j'ai créé moi-même et qui contient un nom d'ordinateur par ligne. Windows PowerShell traite chaque ligne en tant qu'objet ; ce fichier est donc essentiellement une collection contenant ces objets. Cette collection se termine par la variable $names. A l'aide du mot-clé Foreach, je demande à Windows PowerShell d'énumérer la collection $names, en utilisant la variable $name pour représenter l'objet actuel à chaque exécution de la boucle. Le code en boucle se trouve entre les accolades. Ainsi, je vais extraire chaque nom présent dans le fichier vers la ligne de commande. Et, comme vous pouvez le constater dans le résultat suivant la construction, c'est exactement ce que fait Windows PowerShell. L'avantage en termes de scripts d'administration est évident : vous pouvez facilement construire une liste de noms de serveurs, par exemple, et demander à Windows PowerShell d'en extraire les informations, chacun à son tour.

Constructions Real-World

A présent, utilisons les comparaisons logiques, la construction If et la construction Foreach pour créer un outil utile. Je souhaite vérifier rapidement l'état du service Messenger sur un ensemble de serveurs. Comme je m'attends à ce que ce service soit arrêté sur la plupart d'entre eux, je ne veux pas que Windows PowerShell répertorie tous les serveurs dont l'état est celui auquel je m'attends ; je souhaite uniquement une liste des serveurs où le service Messenger est effectivement démarré car ce sont ces derniers qui m'intéressent.

Je sais que l'applet de commande Get-Service de Windows PowerShell peut m'aider à extraire les informations dont j'ai besoin pour l'ordinateur local. Toutefois, je ne peux malheureusement pas atteindre un ordinateur distant, ce qui est en fait mon objectif réel. Fort heureusement, je peux également accéder aux mêmes informations via WMI (Windows Management Instrumentation) à l'aide de l'applet de commande Get-WMIObject, lequel me permet de travailler avec un ordinateur distant. Voici donc le script :

$names = get-content c:\computers.txt
foreach ($name in $names) {
  $svc = get-wmiobject win32_service '
   -computer $name -filter "name='messenger'"
  if ($svc.started -eq $True ) {
    write-host "$name has Messenger running"
  }
}

Notez la présence du caractère ' sur la troisième ligne. Ce dernier indique à Windows PowerShell que la ligne suivante en est la suite. Ce caractère s'avère utile lorsque la ligne entière ne peut pas tenir dans le magazine et nécessite un renvoi à la ligne suivante. Notez également que ma construction If compare $svc.started à $True. La variable $True est une variable spéciale de Windows PowerShell qui représente la valeur booléenne True (vrai). (La variable associée, $False, représente la valeur booléenne False (faux).) En fait, j'aurais pu prendre un petit raccourci :

$names = get-content c:\computers.txt
foreach ($name in $names) {
  $svc = get-wmiobject win32_service '
   -computer $name -filter "name='messenger'"
  if ($svc.started) {
    write-host "$name has Messenger running"
  }
}

N'oubliez pas que la condition de la construction If (si) doit simplement être True (vrai) ou False (faux). Normalement, en comparant deux valeurs, vous obtenez un résultat True (vrai) ou False (faux), comme je l'ai fait dans la première version de ce script. Toutefois, la propriété Started étant soit True (vrai) soit False (faux), il n'est pas nécessaire de la comparer effectivement à ces résultats.

Un outil utile

En conclusion, voici un outil d'administration simple qui se sert de constructions pour effectuer sa tâche. Qu'il soit écrit de manière interactive dans Windows PowerShell ou enregistré dans un fichier PS1 afin de pouvoir le réutiliser aisément, cet outil facile à gérer vous permet de vérifier l'état d'un service sur divers ordinateurs et vous démontre à quel point les constructions s'avèrent utiles dans l'automatisation des tâches d'administration.

Don Jones est le directeur des projets et services de SAPIEN Technologies et le co-auteur de Windows PowerShell : TFM (SAPIEN Press, 2006). Pour contacter Don, rendez-vous sur son site Web à l'adresse suivante : ScriptingAnswers.com.

© 2008 Microsoft Corporation et CMP Media, LLC. Tous droits réservés. Toute reproduction, totale ou partielle, est interdite sans autorisation préalable.