PowerShell et -WhatIf : testez vos commandes et scripts!
Sommaire
I. Présentation
Lorsque l'on rédige un script, on essaie généralement d'y aller petit à petit, et de le tester au fur et à mesure, puis arrive le moment fatidique : il faut exécuter le script. Le problème c'est qu'il n'est pas possible de le tester avant... Heureusement, Microsoft a prévu le coup et à intégré le paramètre -WhatIf à la majorité des commandes PowerShell qui effectue des modifications, sous réserve d'implémentation par les développeurs.
Si une commande est exécutée avec le paramètre -WhatIf, elle ne fera aucune modification sur votre système. Ce qui est intéressant, c'est que grâce à -WhatIf, des informations vont s'afficher dans la console pour indiquer qu'elles sont les actions réalisées pour chaque commande, ainsi que l'objet affecté. Un bon moyen d'anticiper un éventuel bug en complément des tests que l'on peut réaliser progressivement pendant la construction du script.
Tutoriel disponible en version vidéo ⬇
En consultant l'aide d'un cmdlet, on peut rapidement voir si le paramètre -WhatIf est supporté. Par exemple :
Get-Help New-Item
Une autre méthode serait de s'appuyer directement sur l'auto-complétion, tout simplement.
II. WhatIf dans la pratique
A. Premiers pas avec -WhatIf
Nous allons reprendre la commande New-Item citée précédemment et qui va altérer notre système puisqu'elle sert à créer un fichier ou un dossier. Par exemple, nous pouvons créer un fichier nommé "it-connect.txt" dans le répertoire courant, comme ceci :
New-Item -ItemType File -Name "it-connect.txt"
A première vue, rien de dramatique, mais imaginons que l'on ne sait pas trop ce que va faire la commande... Il est alors intéressant d'utiliser le paramètre -WhatIf pour regarder ce qu'elle va faire. Ce qui donne :
New-Item -ItemType File -Name "it-connect.txt" -WhatIf
What if: Performing the operation "Create File" on target "Destination: C:\TEMP\it-connect.txt".
On peut comprendre facilement que cette commande va créer un fichier à l'emplacement suivant : C:\TEMP\. Intéressant, non ?
Dans le même esprit, on peut prendre cette commande :
Get-Process *explorer* | Stop-Process
Si l'on se demande ce qu'elle va faire, on va simplement ajouter WhatIf à la fin :
Get-Process *explorer* | Stop-Process -WhatIf
A la lecture du retour obtenu dans la console, on comprends que la commande va exécuter l'action "Stop-Process" (tuer le processus) sur deux processus ayant les PID 3144 et 7692.
What if: Performing the operation "Stop-Process" on target "explorer (3144)". What if: Performing the operation "Stop-Process" on target "explorer (7692)".
Sur le même principe, on pourrait utiliser WhatIf sur d'autres commandes notamment Stop-Service.
B. La variable $WhatIfPreference
Avec ce que l'on a vu précédemment, c'est pratique mais contraignant : il faut définir -WhatIf sur chaque commande, alors si l'on veut tester un script complet, ça peut vite devenir pénible. En effet, s'il faut s'amuser à ajouter le paramètre sur les différents cmdlets pour le retirer ensuite.... c'est chronophage !
C'est là qu'intervient la variable booléenne $WhatIfPreference, c'est-à-dire qu'elle peut avoir seulement deux valeurs : $true ou $false. Par défaut, la valeur est $false cela signifie que le paramètre WhatIf est désactivé pour l'ensemble des commandes, à moins de le spécifier au niveau d'une commande (comme vu précédemment). A l'inverse, si l'on définit sa valeur sur $true, WhatIf sera actif automatiquement sur toutes les commandes supportées : pratique car on peut basculer d'un mode à l'autre d'une seule commande.
Pour basculer sur le mode $true, il suffit d'exécuter cette commande :
$WhatIfPreference = $true
Si je ré-exécute la commande précédente, on peut voir que le WhatIf s'active sans que je le précise à la fin de la commande ? - Lorsque les tests seront concluants, il suffira de faire machine arrière :
$WhatIfPreference = $false
Pour les développeurs qui souhaitent créer leurs propres commandes, vous pouvez implémenter -WhatIf dans vos fonctions par l'intermédiaire du paramètre "[CmdletBinding(SupportsShouldProcess)]" qui va permettre d'ajouter le support de WhatIf et Confirm à votre fonction. Ce sera à vous ensuite d'alimenter le message qui s'affiche lorsque le WhatIf est appelé ?
A vos tests !