Dominar o parâmetro WhatIf do PowerShell

“Não testo sempre meus scripts, mas quando o faço, faço isso em produção”

Não minta. Você já fez isso antes. Todos nós fizemos em algum momento. Mas não precisa ser arriscado quando se executa scripts do PowerShell em produção. Apenas lembre-se de usar o parâmetro embutido do PowerShell, WhatIf!

Não seria bom saber o que aquele comando do PowerShell faria antes de fazer alterações em seu ambiente? Imagine poder perguntar ao seu comando: “O que você faria se fosse executado?” Você pode usar o parâmetro WhatIf.

Todos os cmdlets compilados do PowerShell incluem um parâmetro chamado WhatIf. Este parâmetro ajuda você a avaliar se um comando funcionará como esperado ou se iniciará uma fusão nuclear.

O útil parâmetro WhatIf não está disponível apenas com todos os cmdlets integrados, mas também com seus scripts e funções avançadas! Se seu código irá alterar coisas em seu ambiente, você tem o benefício de um mecanismo à prova de falhas, caso opte por implementá-lo.

Pré-requisitos

Este artigo será um passo a passo. Se você deseja acompanhar durante esta jornada, deve ter algumas coisas em vigor.

Observe que neste artigo, estarei usando o Visual Studio Code 1.38 (agosto de 2019) em um computador com Windows 10.

O Parâmetro WhatIf do PowerShell: Definido

Em poucas palavras, o parâmetro WhatIf é um parâmetro de comutação incorporado disponível em todas as funções avançadas e cmdlets (ao adicionar a palavra-chave CmdletBinding do PowerShell a scripts e funções). Quando usado, o comando relata o efeito esperado do comando no console. Mas na realidade não executa o comando.

Todos os cmdlets e funções avançadas têm o parâmetro WhatIf disponível. Neste artigo, vamos demonstrar esse parâmetro usando os cmdlets Get-Service, Stop-Service e New-Item.

Verificando o Suporte ao WhatIf do PowerShell

Se você não tem certeza se um determinado comando suporta o WhatIf, existem duas maneiras rápidas de verificar.

Usando Get-Command

Você pode usar o comando Get-Command para visualizar metadados de comando usando o parâmetro Syntax como mostrado abaixo. Se você vir uma referência ao -WhatIf, o WhatIf é suportado.

Get-Command <CommandName> -Syntax

Usando Completar com Tabulação

Você também pode verificar o suporte ao parâmetro WhatIf usando a conclusão com tabulação. Basta digitar o comando que você gostaria de verificar em um console do PowerShell seguido de um espaço, traço, ‘Wh’ e a tecla de tabulação.

Se WhatIf aparecer, você saberá que o comando tem o parâmetro WhatIf.

PS> <CommandName> -Wh[tab]

Usando o Parâmetro WhatIf do PowerShell com Cmdlets

Existem muitas maneiras diferentes de aproveitar o parâmetro WhatIf. Nesta seção, você aprenderá como começar a usar o parâmetro WhatIf imediatamente usando cmdlets integrados.

Criando um Arquivo

Como todos os cmdlets, o cmdlet New-Item possui um parâmetro WhatIf. Neste exemplo, você usará o cmdlet New-Item para criar um arquivo chamado newfile1.txt no mesmo diretório de trabalho.

Se você executasse o comando abaixo, ele criaria o arquivo chamado newfile.txt.

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

Mas e se este comando criar um arquivo que pode potencialmente causar um problema se for criado com falha? Sem problemas. Você pode adicionar o parâmetro WhatIf no final.

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

Parando um Serviço

Você também pode usar o parâmetro WhatIf com o cmdlet Stop-Service. Neste exemplo, você está obtendo uma lista dos cinco primeiros serviços e parando-os com o comando Stop-Service. Mas você não está.

Em vez disso, você apenas vê mensagens de saída no console do PowerShell informando quais serviços o cmdlet Stop-Service teria parado.

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

Alterando o Comportamento Global do WhatIf do Powershell

Neste ponto, você deve saber que o uso do parâmetro WhatIf com um cmdlet ou função avançada apenas simula a operação. Você estava afetando o comportamento do WhatIf no nível do comando.

O comportamento WhatIf também pode ser configurado em um nível mais alto que afeta todos os comandos manipulando a variável automática $WhatIfPreference.

A variável $WhatIfPreference é booleana. Ela só pode ser True ou False. Por padrão, está configurada como False, o que significa que o suporte WhatIf está desativado em todos os comandos, a menos que seja substituído no nível do comando. Se configurado como True, todos os comandos que o suportam, quer usando explicitamente o parâmetro WhatIf ou não, estarão no modo “WhatIf“.

Você pode testar isso alterando o valor de $WhatIfPreference para True via $WhatIfPreference = $true. Você pode ver abaixo que usando New-Item sem o parâmetro WhatIf agora age como se o parâmetro tivesse sido passado.

PS51> $WhatIfPreference = $true

Se você alterou $WhatIfPreference para True, não se esqueça de voltar a configurá-lo como False via $WhatIfPreference = $false.

Nesta seção, você aprendeu como usar o suporte WhatIf com cmdlets existentes. Na próxima ação, você aprenderá como construir o suporte WhatIf em seus scripts e funções personalizados.

Implementando o Suporte WhatIf do PowerShell em Funções

Antes de tentar implementar o suporte WhatIf nos seus scripts, é essencial saber que existe uma maneira errada e uma maneira certa de fazer isso. Você verá nas próximas seções o que são essas maneiras.

Fazendo Errado: Não Reinvente a Roda

Não é incomum para os desenvolvedores de scripts reinventarem a roda e implementarem seu próprio suporte WhatIf com alguma lógica de if/then. Abaixo, você pode ver um exemplo.

Observe que o desenvolvedor definiu seu próprio parâmetro de switch WhatIf. Em seguida, usando o valor desse parâmetro, eles usaram uma construção de if/then para lidar com a lógica quando o parâmetro WhatIf foi utilizado ou não.

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

        [switch]$WhatIf
    )
    
    if ($WhatIf.IsPresent) { # O switch WhatIf está ligado.
        Write-Host "WhatIf: I will remove the log file ""$name""" -ForegroundColor Yellow
    } else {
        # O switch WhatIf está desligado.
        Write-Host "Delete log file ""$name""" -ForegroundColor Green
    }
}

Quando a função acima é executada usando o parâmetro WhatIf, conforme mostrado abaixo, parece que fez seu trabalho. A função na verdade não removeu nada e retornou uma mensagem para o console.

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

Se funciona, então qual é o problema com este método? Porque você está negligenciando as capacidades integradas de uma função avançada. Você precisará construir essa funcionalidade em cada função que criar, em vez de se concentrar apenas no que o comando fará quando estiver desativado.

Em vez disso, não reinvente a roda e use a palavra-chave SupportsShouldProcess combinada com o $PSCmdlet.ShouldProcess(). Isso está chegando.

Fazendo da Maneira Certa: Usando SupportsShouldProcess

Todas as funções que usam a palavra-chave [CmdletBinding()] tornam-nas “avançadas”. Essa palavra-chave adiciona várias capacidades à função, incluindo suporte WhatIf.

Todas as funções avançadas suportam funcionalidade WhatIf, mas depende de você aproveitá-la. Para fazer isso, você deve usar a palavra-chave SupportsShouldProcess entre os parênteses [CmdletBinding()] primeiro, como mostrado abaixo.

[CmdletBinding(SupportsShouldProcess)]

A função agora permite que você chame o método ShouldProcess() na variável de função $PSCmdlet para determinar se o parâmetro WhatIf foi passado para a função ou não. Quando o parâmetro WhatIf é usado, ShouldProcess() retorna Falso. Caso contrário, sempre retornará Verdadeiro.

Function Remove-LogFile {
     [cmdletbinding(SupportsShouldProcess)]
     param (
         [Parameter(Mandatory)]
         [string]$name
     )
     if ($PSCmdlet.ShouldProcess($name)) {
         ## O parâmetro -WhatIf NÃO foi usado. A função deve processar normalmente.
         Write-Host ("Delete log file " + $name) -ForegroundColor Green
     } else {
         ## O parâmetro -WhatIf foi usado. A função NÃO deve processar.
     }
 }
WHATIF PARAMETER USED SHOULDPROCESS() RESULT
True False
False True

Agora você pode ver abaixo quando Remove-LogFile é executado com o parâmetro WhatIf; ele exibe o mesmo comportamento dos cmdlets integrados.

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

Resumo

Neste artigo, você aprendeu sobre o parâmetro WhatIf do PowerShell. Agora você deve entender como ele funciona e quais benefícios pode trazer.

Você também deve saber que não é necessário reinventar a roda na próxima vez que precisar de uma proteção para suas funções do PowerShell. Em vez disso, aproveite o suporte existente para o WhatIf no PowerShell!

Leitura Adicional

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