Maîtriser le paramètre PowerShell WhatIf

« Je ne teste pas toujours mes scripts, mais quand je le fais, je le fais en production »

Ne mens pas. Tu l’as déjà fait. Nous l’avons tous fait à un moment donné. Cependant, cela ne doit pas nécessairement être risqué lorsque vous exécutez des scripts PowerShell en production. Souvenez-vous simplement d’utiliser le paramètre intégré WhatIf de PowerShell!

Ne serait-il pas agréable de savoir ce que cette commande PowerShell ferait avant de modifier votre environnement? Imaginez pouvoir demander à votre commande : « Que ferais-tu si tu étais exécuté ? » Vous pouvez utiliser le paramètre WhatIf.

Tous les cmdlets PowerShell compilés incluent un paramètre appelé WhatIf. Ce paramètre vous aide à évaluer si une commande fonctionnera comme vous le souhaitez ou si elle déclenchera une fusion nucléaire.

Le pratique paramètre WhatIf n’est pas seulement disponible avec tous les cmdlets intégrés, mais également avec vos scripts et fonctions avancées ! Si votre code va modifier des choses dans votre environnement, vous avez l’avantage d’un mécanisme de sécurité en cas de besoin.

Prérequis

Cet article va être un guide pas à pas. Si vous souhaitez suivre cette démarche, vous devez avoir quelques éléments en place.

Notez que dans cet article, je vais utiliser Visual Studio Code 1.38 (août 2019) sur une machine Windows 10.

Le Paramètre WhatIf de PowerShell : Définition

En résumé, le paramètre WhatIf est un paramètre de commutateur intégré disponible avec toutes les fonctions avancées et cmdlets (en ajoutant le mot-clé CmdletBinding de PowerShell aux scripts et fonctions). Lorsqu’il est utilisé, la commande rapporte l’effet attendu de la commande à la console. Mais n’exécute pas réellement la commande.

Tous les cmdlets et fonctions avancées ont le paramètre WhatIf disponible. Dans cet article, nous allons démontrer ce paramètre en utilisant les cmdlets Get-Service, Stop-Service, et New-Item.

Vérification de la prise en charge de WhatIf dans PowerShell

Si vous n’êtes pas sûr qu’une commande particulière prend en charge WhatIf, il existe deux moyens rapides pour vérifier.

Utilisation de Get-Command

Vous pouvez utiliser la commande Get-Command pour afficher les métadonnées de la commande en utilisant le paramètre Syntax comme indiqué ci-dessous. Si vous voyez une référence à -WhatIf, WhatIf est pris en charge.

Get-Command <CommandName> -Syntax

Utilisation de la complétion automatique

Vous pouvez également vérifier la prise en charge du paramètre WhatIf en utilisant la complétion automatique. Il suffit de taper la commande que vous souhaitez vérifier dans une console PowerShell suivi d’un espace, d’un tiret, de ‘Wh’ et de la touche tabulation.

Si WhatIf apparaît, vous savez que la commande dispose du paramètre WhatIf.

PS> <CommandName> -Wh[tab]

Utilisation du paramètre PowerShell WhatIf avec les cmdlets

Il existe de nombreuses façons différentes dont vous pouvez tirer parti du paramètre WhatIf. Dans cette section, vous apprendrez comment commencer à utiliser le paramètre WhatIf immédiatement à l’aide des cmdlets intégrés.

Création d’un fichier

Comme tous les cmdlets, le cmdlet New-Item a un paramètre WhatIf. Dans cet exemple, vous utiliserez le cmdlet New-Item pour créer un fichier nommé newfile1.txt dans le même répertoire de travail.

Si vous deviez exécuter la commande ci-dessous, elle créerait le fichier appelé newfile.txt.

PS51> New-Item -ItemType File -Path .\newfile1.txt

Mais que se passe-t-il si cette commande crée un fichier qui pourrait potentiellement poser problème s’il était créé avec succès? Pas de problème. Vous pouvez ajouter le paramètre WhatIf à la fin.

New-Item -ItemType File -Path .\newfile1.txt -WhatIf

Arrêt d’un service

Vous pouvez également utiliser le paramètre WhatIf avec le cmdlet Stop-Service. Dans cet exemple, vous obtenez une liste des cinq premiers services et les arrêtez avec la commande Stop-Service. Mais non, vous ne le faites pas.

À la place, vous voyez simplement un message de sortie dans la console PowerShell vous informant des services que le cmdlet Stop-Service aurait arrêtés.

PS51> (Get-Service)[0..4] | Stop-Service -WhatIf

Modification du comportement global de WhatIf dans PowerShell

À ce stade, vous devriez savoir que l’utilisation du paramètre WhatIf avec un cmdlet ou une fonction avancée simule uniquement l’opération. Vous affectiez le comportement de WhatIf au niveau de la commande.

Le comportement WhatIf peut également être défini à un niveau supérieur qui affecte toutes les commandes en manipulant la variable automatique $WhatIfPreference.

La variable $WhatIfPreference est booléenne. Elle ne peut être que Vrai ou Faux. Par défaut, elle est définie sur Faux, ce qui signifie que le support WhatIf est désactivé sur toutes les commandes sauf si elles sont remplacées au niveau de la commande. S’il est défini sur Vrai, toutes les commandes qui le supportent, qu’elles utilisent explicitement le paramètre WhatIf ou non, seront en mode « WhatIf« .

Vous pouvez tester cela en modifiant la valeur de $WhatIfPreference sur Vrai via $WhatIfPreference = $true. Vous pouvez voir ci-dessous que l’utilisation de New-Item sans le paramètre WhatIf agit maintenant comme si le paramètre avait été passé.

PS51> $WhatIfPreference = $true

Si vous avez modifié $WhatIfPreference sur Vrai, n’oubliez pas de le rechanger sur Faux via $WhatIfPreference = $false.

Dans cette section, vous avez appris comment utiliser le support WhatIf avec les cmdlets existants. Dans l’action suivante, vous apprendrez comment intégrer le support WhatIf dans vos scripts et fonctions personnalisés.

Implémentation du support Powershell WhatIf dans les fonctions

Avant d’essayer de mettre en œuvre la prise en charge de WhatIf dans vos scripts, il est essentiel de savoir qu’il y a une mauvaise façon et une bonne façon de le faire. Vous verrez dans les prochaines sections ce que sont ces façons.

Faire de la mauvaise façon : Ne pas réinventer la roue

Il n’est pas rare que les développeurs de scripts réinventent la roue et mettent en œuvre leur propre prise en charge de WhatIf avec une logique if/then. Vous pouvez voir ci-dessous un exemple.

Remarquez que le développeur a défini son propre paramètre de commutateur WhatIf. Ensuite, en utilisant la valeur de ce paramètre, il a utilisé une construction if/then pour gérer la logique lorsque le paramètre WhatIf était utilisé ou non.

Function Remove-LogFile {
    param (
        [Parameter(Mandatory)]
        [string]$name,

        [switch]$WhatIf
    )
    
    if ($WhatIf.IsPresent) { # Le commutateur WhatIf est activé.
        Write-Host "WhatIf: I will remove the log file ""$name""" -ForegroundColor Yellow
    } else {
        # Le commutateur WhatIf est désactivé.
        Write-Host "Delete log file ""$name""" -ForegroundColor Green
    }
}

Lorsque la fonction ci-dessus est exécutée en utilisant le paramètre WhatIf comme indiqué ci-dessous, on dirait qu’elle a fait son travail. La fonction n’a pas réellement supprimé quoi que ce soit et renvoie un message à la console.

PS51> Remove-LogFile -name log.txt -WhatIf

Si cela fonctionne, alors qu’est-ce qui ne va pas avec cette méthode ? Parce que vous négligez les capacités intégrées d’une fonction avancée. Vous devrez intégrer cette fonctionnalité dans chaque fonction que vous créez au lieu de vous concentrer uniquement sur ce que la commande fera lorsqu’elle sera désactivée.

Au lieu de réinventer la roue, utilisez le mot-clé SupportsShouldProcess combiné avec $PSCmdlet.ShouldProcess(). C’est à venir.

Faire les choses correctement : Utilisation de SupportsShouldProcess

Toutes les fonctions utilisant le mot-clé [CmdletBinding()] les rendent « avancées ». Ce mot-clé ajoute différentes fonctionnalités à la fonction, y compris le support de WhatIf.

Toutes les fonctions avancées prennent en charge la fonctionnalité WhatIf, mais c’est à vous d’en tirer parti. Pour ce faire, vous devez utiliser le mot-clé SupportsShouldProcess entre les parenthèses de [CmdletBinding()] comme indiqué ci-dessous.

[CmdletBinding(SupportsShouldProcess)]

La fonction vous permet maintenant d’appeler la méthode ShouldProcess() sur la variable de fonction $PSCmdlet pour déterminer si le paramètre WhatIf a été passé à la fonction ou non. Lorsque le paramètre WhatIf est utilisé, ShouldProcess() renvoie False. Sinon, il renverra toujours True.

Function Remove-LogFile {
     [cmdletbinding(SupportsShouldProcess)]
     param (
         [Parameter(Mandatory)]
         [string]$name
     )
     if ($PSCmdlet.ShouldProcess($name)) {
         ## Le paramètre -WhatIf n'a PAS été utilisé. La fonction doit être traitée normalement.
         Write-Host ("Delete log file " + $name) -ForegroundColor Green
     } else {
         ## Le paramètre -WhatIf a été utilisé. La fonction ne doit PAS être traitée.
     }
 }
WHATIF PARAMETER USED SHOULDPROCESS() RESULT
True False
False True

Maintenant, vous pouvez voir ci-dessous quand Remove-LogFile est exécuté avec le paramètre WhatIf; il affiche le même comportement que les cmdlets intégrés.

PS51> Remove-LogFile -name log.txt -WhatIf

Résumé

Dans cet article, vous avez appris sur le paramètre WhatIf de PowerShell. Vous devriez maintenant comprendre comment il fonctionne et les avantages qu’il peut apporter.

Vous devriez également savoir qu’il est inutile de réinventer la roue la prochaine fois que vous avez besoin d’une sécurité pour vos fonctions PowerShell. Au lieu de cela, tirez parti du support existant de WhatIf dans PowerShell!

Lecture complémentaire

Source:
https://adamtheautomator.com/powershell-whatif/