Na programação PowerShell, a validação de parâmetros é uma técnica essencial para garantir que as funções e scripts recebam dados corretos e esperados. Em vez de escrever código manual para verificar cada entrada, você pode usar atributos de validação declarativos que são processados automaticamente pelo runtime do PowerShell. Isso reduz erros, melhora a legibilidade e proporciona mensagens de erro consistentes.

Esta aula explora quatro atributos fundamentais: [ValidateNotNull], [ValidateSet], [ValidatePattern] e [ValidateRange]. Cada um atende a um cenário específico, desde garantir que um parâmetro não seja nulo até restringir valores a um conjunto fixo, validar formato com expressões regulares ou limitar números a um intervalo. Dominar esses atributos eleva a qualidade dos seus scripts e funções.

[ValidateNotNull]

O atributo [ValidateNotNull] garante que o valor passado para o parâmetro não seja $null. Se o usuário omitir o parâmetro ou passar explicitamente $null, o PowerShell lançará um erro de validação antes mesmo da execução do corpo da função. Isso é útil para parâmetros obrigatórios que não podem ser nulos.

Por exemplo, considere uma função que requer um nome de arquivo. Sem validação, o código poderia tentar acessar um caminho nulo, causando exceções inesperadas. Com [ValidateNotNull], você impede esse cenário de forma simples.

function Get-FileInfo {
    param(
        [ValidateNotNull()]
        [string]$Path
    )
    Get-Item -Path $Path
}

# Teste: Get-FileInfo -Path $null  # Gera erro: Cannot validate argument on parameter 'Path'

Note que [ValidateNotNull] não impede que a string seja vazia (''), apenas $null. Para strings vazias, use [ValidateNotNullOrEmpty] (não abordado nesta aula).

[ValidateSet]

O atributo [ValidateSet] restringe o valor do parâmetro a um conjunto predefinido de opções. Se o usuário fornecer um valor que não está na lista, o PowerShell exibe um erro com as opções válidas. Isso é ideal para parâmetros que representam escolhas fixas, como modos de operação, tipos de saída ou estados.

O conjunto é definido como uma lista de strings no atributo. A comparação é case-insensitive por padrão, mas você pode adicionar o parâmetro IgnoreCase = $false para tornar sensível a maiúsculas/minúsculas.

function Set-LogLevel {
    param(
        [ValidateSet('Debug', 'Info', 'Warning', 'Error')]
        [string]$Level
    )
    Write-Host "Log level set to: $Level"
}

# Uso correto: Set-LogLevel -Level 'Warning'
# Uso incorreto: Set-LogLevel -Level 'Verbose'  # Erro: The argument "Verbose" does not belong to the set ...

Além de strings, [ValidateSet] também pode ser usado com outros tipos, como inteiros ou enums, desde que os valores sejam literais. É uma forma elegante de implementar um menu de opções sem código adicional.

[ValidatePattern]

O atributo [ValidatePattern] valida o valor do parâmetro contra uma expressão regular (regex). Se o valor não corresponder ao padrão, um erro é gerado. Isso é poderoso para validar formatos como endereços de e-mail, números de telefone, códigos postais, etc.

Você pode especificar a regex diretamente no atributo. Lembre-se de escapar caracteres especiais quando necessário. O PowerShell usa o motor regex do .NET, que oferece suporte a uma ampla gama de padrões.

function Test-Email {
    param(
        [ValidatePattern('^[\w.-]+@[\w.-]+\.\w+$')]
        [string]$Email
    )
    Write-Host "Email $Email is valid (according to pattern)"
}

# Uso: Test-Email -Email 'user@example.com'  # OK
# Uso: Test-Email -Email 'not-an-email'       # Erro

É importante testar bem a regex para evitar falsos positivos ou negativos. [ValidatePattern] não substitui uma validação completa (ex.: verificar se o domínio existe), mas é uma primeira barreira eficiente.

[ValidateRange]

O atributo [ValidateRange] limita o valor de um parâmetro numérico a um intervalo especificado (mínimo e máximo). Se o valor estiver fora desse intervalo, um erro é gerado. É útil para parâmetros que representam idades, quantidades, tamanhos, etc.

O intervalo é definido por dois argumentos: o mínimo e o máximo. Ambos são inclusivos. Você pode usar inteiros, decimais ou até mesmo outros tipos numéricos, desde que suportem comparação.

function Set-Age {
    param(
        [ValidateRange(0, 150)]
        [int]$Age
    )
    Write-Host "Age set to: $Age"
}

# Uso: Set-Age -Age 25  # OK
# Uso: Set-Age -Age -1  # Erro: The argument -1 is not in the range ...

Para números de ponto flutuante, use [double] ou [decimal]. O intervalo pode ser definido com variáveis, mas geralmente são literais.

Boas Práticas e Observações Finais

Ao usar validação de parâmetros, lembre-se de que ela ocorre antes da execução do corpo da função, garantindo que entradas inválidas sejam rejeitadas rapidamente. Combine múltiplos atributos quando necessário, como [ValidateNotNull()] com [ValidateSet()]. No entanto, evite validações excessivas que possam tornar o código rígido demais. Sempre documente os parâmetros com param() e comentários para usuários.

Além disso, você pode criar funções de validação personalizadas com [ValidateScript()], mas isso foge ao escopo desta aula. Pratique com os exercícios abaixo para fixar os conceitos.

Referências

Exercícios

  1. Crie uma função chamada Set-ProcessPriority que aceita um parâmetro Priority do tipo [string] e usa [ValidateSet] para aceitar apenas 'Low', 'Normal', 'High' e 'Realtime'. A função deve exibir o valor recebido.

    ✓ Resposta:
    function Set-ProcessPriority {
        param(
            [ValidateSet('Low', 'Normal', 'High', 'Realtime')]
            [string]$Priority
        )
        Write-Host "Priority set to: $Priority"
    }
  2. Escreva uma função Get-UserAge que aceita um parâmetro Age do tipo [int] e usa [ValidateRange] para garantir que a idade esteja entre 0 e 120. Se válido, exiba a idade.

    ✓ Resposta:
    function Get-UserAge {
        param(
            [ValidateRange(0, 120)]
            [int]$Age
        )
        Write-Host "User age: $Age"
    }
  3. Crie uma função Test-ZipCode que aceita um parâmetro ZipCode do tipo [string] e usa [ValidatePattern] para validar que o código postal brasileiro tem 8 dígitos (formato: 12345-678 ou 12345678). Dica: regex: ^\d{5}-?\d{3}$.

    ✓ Resposta:
    function Test-ZipCode {
        param(
            [ValidatePattern('^\d{5}-?\d{3}$')]
            [string]$ZipCode
        )
        Write-Host "Zip code $ZipCode is valid."
    }
  4. Escreva uma função Connect-Server que aceita um parâmetro ServerName do tipo [string] e usa [ValidateNotNull()] para garantir que não seja nulo. A função deve exibir o nome do servidor.

    ✓ Resposta:
    function Connect-Server {
        param(
            [ValidateNotNull()]
            [string]$ServerName
        )
        Write-Host "Connecting to $ServerName"
    }
  5. Crie uma função Set-Volume que aceita um parâmetro Level do tipo [int] e usa [ValidateRange] para permitir valores de 0 a 100. Além disso, use [ValidateNotNull()] para garantir que não seja nulo (embora int não possa ser nulo, a prática é válida). Exiba o nível.

    ✓ Resposta:
    function Set-Volume {
        param(
            [ValidateNotNull()]
            [ValidateRange(0, 100)]
            [int]$Level
        )
        Write-Host "Volume set to: $Level"
    }