Dominare il parametro WhatIf di PowerShell

Non sempre testo i miei script, ma quando lo faccio, lo faccio in produzione

Non mentire. Lo hai fatto prima. Tutti l’abbiamo fatto in qualche momento. Non deve per forza essere rischioso quando si eseguono script PowerShell in produzione. Ricordati semplicemente di utilizzare il parametro integrato di PowerShell WhatIf!

Non sarebbe bello sapere cosa farebbe quel comando PowerShell prima che apporti modifiche al tuo ambiente? Immagina di poter chiedere al tuo comando: “Cosa faresti se dovessi essere eseguito?” Puoi utilizzare il parametro WhatIf.

Tutti i cmdlet PowerShell compilati includono un parametro chiamato WhatIf. Questo parametro ti aiuta a valutare se un comando funzionerà come previsto o se avvierà una fusione nucleare.

Il pratico parametro WhatIf non è disponibile solo con tutti i cmdlet integrati, ma anche per i tuoi script e le funzioni avanzate! Se il tuo codice cambierà le cose nel tuo ambiente, hai il vantaggio di un meccanismo di sicurezza in caso decidi di implementarlo.

Prerequisiti

Questo articolo sarà una guida dettagliata. Se desideri seguirmi durante questo viaggio, dovresti avere alcune cose in atto.

Nel presente articolo, userò Visual Studio Code 1.38 (agosto 2019) su una macchina Windows 10.

Il parametro PowerShell WhatIf: Definito

In poche parole, il parametro WhatIf è un parametro integrato parametro di switch disponibile con tutte le funzioni avanzate e i cmdlet (aggiungendo la parola chiave PowerShell CmdletBinding agli script e alle funzioni). Quando viene utilizzato, il comando riporta l’effetto previsto del comando alla console. Ma non esegue effettivamente il comando.

Tutti i cmdlet e le funzioni avanzate hanno il parametro WhatIf disponibile. In questo articolo, dimostreremo questo parametro utilizzando i cmdlet Get-Service, Stop-Service e New-Item.

Verifica del supporto di WhatIf in PowerShell

Se non sei sicuro che un determinato comando supporti WhatIf, ci sono due modi rapidi per verificare.

Utilizzo di Get-Command

Puoi utilizzare il comando Get-Command per visualizzare i metadati del comando utilizzando il parametro Syntax come mostrato di seguito. Se vedi un riferimento a -WhatIf, WhatIf è supportato.

Get-Command <CommandName> -Syntax

Utilizzo del completamento automatico

Puoi anche verificare il supporto del parametro WhatIf utilizzando il completamento automatico. Basta digitare il comando che desideri controllare in una console PowerShell seguito da uno spazio, un trattino, ‘Wh’ e il tasto tab.

Se compare WhatIf, sai che quel comando ha il parametro WhatIf.

PS> <CommandName> -Wh[tab]

Utilizzo del parametro PowerShell WhatIf con i Cmdlet

Ci sono molti modi diversi in cui puoi sfruttare il parametro WhatIf. In questa sezione, imparerai come puoi iniziare a utilizzare immediatamente il parametro WhatIf utilizzando cmdlet integrati.

Creazione di un file

Come tutti i cmdlet, il cmdlet New-Item ha un parametro WhatIf. In questo esempio, utilizzerai il cmdlet New-Item per creare un file chiamato newfile1.txt nella stessa directory di lavoro.

Se eseguissi il comando sottostante, creerebbe il file chiamato newfile.txt.

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

Ma cosa succede se questo comando crea un file che potrebbe potenzialmente causare un problema se fosse creato senza successo? Nessun problema. Puoi aggiungere il parametro WhatIf alla fine.

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

Arresto di un servizio

Puoi anche utilizzare il parametro WhatIf con il cmdlet Stop-Service. In questo esempio, stai ottenendo un elenco dei primi cinque servizi e li stai arrestando con il comando Stop-Service. Ma non lo stai facendo.

Invece, stai solo visualizzando un messaggio di output sulla console di PowerShell che ti informa su quali servizi il cmdlet Stop-Service avrebbe arrestato.

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

Cambiare il comportamento di WhatIf di Powershell globalmente

A questo punto, dovresti sapere che utilizzare il parametro WhatIf con un cmdlet o una funzione avanzata simula solo l’operazione. Stavi influenzando il comportamento di WhatIf a livello di comando.

Il comportamento di WhatIf può anche essere impostato a un livello superiore che influisce su tutti i comandi manipolando la variabile automatica $WhatIfPreference.

La variabile $WhatIfPreference è booleana. Può essere solo Vero o Falso. Per impostazione predefinita, è impostata su Falso, il che significa che il supporto di WhatIf è disabilitato su tutti i comandi a meno che non venga sovrascritto a livello di comando. Se impostato su Vero, tutti i comandi che lo supportano, che utilizzino esplicitamente il parametro WhatIf o meno, saranno in modalità “WhatIf“.

Puoi testare ciò cambiando il valore di $WhatIfPreference in Vero tramite $WhatIfPreference = $true. Puoi vedere di seguito che utilizzando New-Item senza il parametro WhatIf ora si comporta come se il parametro fosse stato passato.

PS51> $WhatIfPreference = $true

Se hai cambiato $WhatIfPreference in Vero, non dimenticare di ripristinarlo a Falso tramite $WhatIfPreference = $false.

In questa sezione, hai imparato come utilizzare il supporto WhatIf con i cmdlet esistenti. Nella prossima azione, imparerai come integrare il supporto WhatIf nei tuoi script e funzioni personalizzati.

Implementare il Supporto di WhatIf in PowerShell nelle Funzioni

Prima di cercare di implementare il supporto WhatIf nei tuoi script, è essenziale sapere che c’è un modo sbagliato e un modo giusto di farlo. Vedrai nelle prossime sezioni quali sono.

Farlo nel modo sbagliato: Non reinventare la ruota

Non è raro che gli sviluppatori di script reinventino la ruota e implementino il loro proprio supporto WhatIf con una logica if/then. Di seguito puoi vedere un esempio.

Nota che lo sviluppatore ha definito il proprio parametro switch WhatIf. Quindi, utilizzando il valore di quel parametro, hanno utilizzato una costruzione if/then per gestire la logica quando il parametro WhatIf era stato utilizzato o meno.

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

        [switch]$WhatIf
    )
    
    if ($WhatIf.IsPresent) { # L'interruttore WhatIf è attivo.
        Write-Host "WhatIf: I will remove the log file ""$name""" -ForegroundColor Yellow
    } else {
        # L'interruttore WhatIf è disattivo.
        Write-Host "Delete log file ""$name""" -ForegroundColor Green
    }
}

Quando la funzione sopra viene eseguita utilizzando il parametro WhatIf come mostrato di seguito, sembra che abbia fatto il suo lavoro. La funzione non ha effettivamente rimosso nulla e ha restituito un messaggio alla console.

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

Se funziona, allora qual è il problema con questo metodo? Perché stai trascurando le capacità integrate di una funzione avanzata. Dovrai costruire questa funzionalità in ogni funzione che crei invece di concentrarti solo su cosa farà il comando quando è disattivato.

Invece, non reinventare la ruota e utilizza la parola chiave SupportsShouldProcess combinata con il $PSCmdlet.ShouldProcess(). Questo è in arrivo.

Farlo Correttamente: Utilizzando SupportsShouldProcess

Tutte le funzioni che utilizzano il [CmdletBinding()] le rendono “avanzate”. Questa parola chiave aggiunge varie funzionalità alla funzione, inclusa il supporto a WhatIf.

Tutte le funzioni avanzate supportano la funzionalità WhatIf, ma dipende da te approfittarne. Per farlo, devi utilizzare prima la parola chiave SupportsShouldProcess tra le parentesi di [CmdletBinding()] come mostrato di seguito.

[CmdletBinding(SupportsShouldProcess)]

La funzione ora ti consente di chiamare il metodo ShouldProcess() sulla variabile di funzione $PSCmdlet per determinare se il parametro WhatIf è stato passato alla funzione o no. Quando viene utilizzato il parametro WhatIf, ShouldProcess() restituisce Falso. Altrimenti, restituirà sempre True.

Function Remove-LogFile {
     [cmdletbinding(SupportsShouldProcess)]
     param (
         [Parameter(Mandatory)]
         [string]$name
     )
     if ($PSCmdlet.ShouldProcess($name)) {
         ## Il parametro -WhatIf NON è stato utilizzato. La funzione dovrebbe elaborare normalmente.
         Write-Host ("Delete log file " + $name) -ForegroundColor Green
     } else {
         ## Il parametro -WhatIf è stato utilizzato. La funzione NON dovrebbe elaborare.
     }
 }
WHATIF PARAMETER USED SHOULDPROCESS() RESULT
True False
False True

Ora puoi vedere di seguito quando viene eseguito Remove-LogFile con il parametro WhatIf; visualizza lo stesso comportamento dei cmdlet incorporati.

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

Riepilogo

In questo articolo hai appreso sul parametro PowerShell WhatIf. Ora dovresti capire come funziona e quali benefici può portare.

Dovresti anche sapere di non reinventare la ruota la prossima volta che hai bisogno di un’opzione di sicurezza per le tue funzioni PowerShell. Invece, sfrutta il supporto esistente per WhatIf di PowerShell!

Ulteriori Letture

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