Domine o parâmetro WhatIf do PowerShell

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

Não minta. Você já fez isso antes. Todos nós já fizemos em algum momento. Não precisa ser arriscado quando se executa scripts do PowerShell em produção. Apenas lembre-se de usar o parâmetro integrado 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 do PowerShell compilados incluem um parâmetro chamado WhatIf. Este parâmetro ajuda você a avaliar se um comando funcionará como você espera ou se iniciará um derretimento 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 o seu código alterar coisas em seu ambiente, você tem o benefício de um mecanismo de segurança caso escolha implementá-lo.

Pré-requisitos

Este artigo será um tutorial. Se você deseja acompanhar esta jornada, deve ter algumas coisas em seu lugar.

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 switch integrado disponível em todas as funções avançadas e cmdlets (ao adicionar a palavra-chave CmdletBinding do PowerShell em scripts e funções). Quando utilizado, 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, demonstraremos este parâmetro usando os cmdlets Get-Service, Stop-Service e New-Item.

Verificando o Suporte ao WhatIf no PowerShell

Se você não tem certeza se um comando específico 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ê ver uma referência a -WhatIf, o WhatIf é suportado.

Get-Command <CommandName> -Syntax

Usando Complemento de Tabulação

Você também pode verificar o suporte ao parâmetro WhatIf usando a tabulação. Simplesmente digite 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 PowerShell WhatIf com Cmdlets

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

Criando um Arquivo

Como todos os cmdlets, o cmdlet New-Item tem 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 esse comando criar um arquivo que possa potencialmente causar um problema se fosse criado sem sucesso? Sem problemas. Você pode adicionar o parâmetro WhatIf ao 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 primeiros cinco serviços e os parando com o comando Stop-Service. Mas você não está.

Em vez disso, você apenas vê uma mensagem 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 do WhatIf no Powershell Globalmente

Neste ponto, você deve saber que usar o 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 definido em um nível mais alto, afetando todos os comandos ao manipular a variável automática $WhatIfPreference.

A variável $WhatIfPreference é booleana. Pode ser apenas True ou False. Por padrão, é definida como False, o que significa que o suporte ao WhatIf está desativado em todos os comandos, a menos que seja substituído no nível do comando. Se definido como True, todos os comandos que o suportam, seja explicitamente usando o parâmetro WhatIf ou não, estarão em modo “WhatIf”.

Você pode testar isso alterando o valor de $WhatIfPreference para True via $WhatIfPreference = $true. Você pode ver abaixo que, ao usar New-Item sem o parâmetro WhatIf, agora ele 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 definir 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 implementar o suporte WhatIf em seus scripts e funções personalizados.

Implementando o Suporte WhatIf no PowerShell em Funções

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

Fazendo Errado: Não Reinvente a Roda

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

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

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

        [switch]$WhatIf
    )
    
    if ($WhatIf.IsPresent) { # A comutação WhatIf está ligada.
        Write-Host "WhatIf: I will remove the log file ""$name""" -ForegroundColor Yellow
    } else {
        # A comutação WhatIf está desligada.
        Write-Host "Delete log file ""$name""" -ForegroundColor Green
    }
}

Quando a função acima é executada usando o parâmetro WhatIf, como mostrado abaixo, parece que ela fez o 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 todas as funções que você criar, em vez de apenas focar no que o comando fará quando ele estiver desligado.

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

Fazendo da Maneira Certa: Utilizando SupportsShouldProcess

Todas as funções que utilizam a palavra-chave [CmdletBinding()] tornam-se “avançadas”. Essa palavra-chave adiciona diversas capacidades à função, incluindo o suporte para WhatIf.

Todas as funções avançadas suportam a funcionalidade WhatIf, mas cabe a você aproveitá-la. Para fazer isso, você deve utilizar a palavra-chave SupportsShouldProcess entre os parênteses de [CmdletBinding()], conforme 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 False. Caso contrário, sempre retornará True.

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

Agora você pode ver abaixo quando o comando 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 salvaguarda para suas funções do PowerShell. Em vez disso, aproveite o suporte existente ao WhatIf no PowerShell!

Leitura adicional

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