Quando você está escrevendo um script ou função do PowerShell, muitas vezes deseja aceitar a entrada do usuário por meio de parâmetros. Se você não limitar os valores que esses parâmetros aceitam, não poderá garantir que haja situações em que valores inadequados sejam fornecidos. Neste artigo, aprenda como usar o atributo de validação de parâmetro ValidateSet do PowerShell para limitar esses valores apenas aos que você define.
Ao escrever um script ou função do PowerShell, você pode usar muitos atributos de validação diferentes para verificar se os valores fornecidos para seus parâmetros são aceitáveis e alertar o usuário se não forem.
Este artigo se concentra no atributo de validação ValidateSet. Você aprenderá o que ValidateSet faz, por que você pode querer usar ValidateSet em seu código e como fazer isso. Você também aprenderá sobre o recurso de conclusão de tabulação que é habilitado pelo ValidateSet e ajudará os usuários do seu código a fornecer valores de parâmetro válidos.
PowerShell ValidateSet: Uma Breve Visão Geral
ValidateSet é um atributo de parâmetro que permite definir um conjunto de elementos que são aceitos apenas como o valor para esse parâmetro.
Por exemplo, talvez você tenha um script que é definido para funcionar com controladores de domínio do Active Directory. Este script tem um parâmetro que especifica o nome de um controlador de domínio. Não faria sentido limitar a lista de valores aceitáveis aos nomes reais dos controladores de domínio? Não há motivo para o usuário poder usar “foobar” como um valor quando você sabe de antemão quais valores o script precisa. ValidateSet oferece essa capacidade.
Requisitos
Este artigo será um guia de aprendizagem. Se você planeja acompanhar, precisará do seguinte:
- Visual Studio Code ou qualquer outro editor de código. Vou usar o Visual Studio Code.
- Pelo menos PowerShell 5.1 para a maior parte do código neste artigo. Há uma seção que exige PowerShell 6.1 ou posterior, e eu vou identificar quando chegarmos lá
Todo o código neste artigo foi testado nos seguintes ambientes:
Operating System | PowerShell Versions |
---|---|
Windows 7 SP1 | 5.1, Core 6.2 |
Windows 10 1903 | 5.1, Core 6.2 |
Linux Mint 19.2 | Core 6.2 |
Para ajudar a explicar os conceitos em torno de ValidateSet, você vai construir um pequeno script chamado Get-PlanetSize.ps1. Este script retorna informações sobre os tamanhos dos planetas em nosso sistema solar.
Você começará com um script simples e gradualmente melhorará sua capacidade de lidar com a entrada do usuário final e facilitar a descoberta de seus possíveis valores de parâmetros.
Começando
Para começar, copie e cole o código PowerShell abaixo no seu editor de texto favorito e salve-o como Get-PlanetSize.ps1.
Execute o script a partir de um prompt do PowerShell e você deverá obter o seguinte:
Informativo, mas não muito flexível; as informações para todos os planetas são retornadas, mesmo se você só quiser as informações para Marte.
Talvez você queira a capacidade de especificar um único planeta em vez de retornar todos eles. Você pode fazer isso introduzindo um parâmetro. Vamos ver como fazer isso a seguir.
Aceitando Entrada usando um Parâmetro
Para permitir que o script aceite um parâmetro, adicione um bloco Param()
ao topo do script. Chame o parâmetro de Planet
. Um bloco Param()
adequado se parece com o exemplo abaixo.
No exemplo abaixo, a linha [Parameter(Mandatory)]
garante que um nome de planeta seja sempre fornecido ao script. Se estiver faltando, o script solicitará um.
A maneira mais simples de incorporar esse parâmetro Planet
ao script é alterar a linha $planets.keys | Foreach-Object {
para $Planet | Foreach-Object {
. Agora você não está mais dependendo da hashtable definida estaticamente anteriormente e, em vez disso, está lendo o valor do parâmetro Planet
.
Agora, se você executar o script e especificar um planeta usando o parâmetro Planet
, verá apenas informações sobre aquele planeta específico.
Excelente. Script concluído? Talvez não.
As Opções são Muito Abertas
O que acontece se você tentar encontrar o diâmetro do planeta Barsoom usando Get-PlanetSize.ps1?
Hmm, isso não está certo. Barsoom não está na lista de planetas, mas o script é executado mesmo assim. Como podemos corrigir isso?
O problema aqui é que o script aceita qualquer entrada e a utiliza, independentemente de ser ou não um valor válido. O script precisa de uma maneira de limitar quais valores são aceitos para o parâmetro Planet
. Introduza ValidateSet!
Garantindo que Apenas Certos Valores são Utilizados
A ValidateSet list is a comma-separated list of string values, wrapped in single or double-quotes. Adding a ValidateSet attribute to a script or function parameter consists of adding a line of text to the Param()
block, as shown below. Replace the Param()
block in your copy of Get-PlanetSize.ps1 with the one below and save the file.
Tente executar o script novamente usando Barsoom como seu parâmetro Planet
. Agora, uma mensagem de erro útil é retornada. A mensagem é específica sobre o que deu errado e até fornece uma lista de valores possíveis para o parâmetro.
Tornando o ValidateSet do PowerShell Sensível a Maiúsculas e Minúsculas
Por padrão, o atributo ValidateSet não faz distinção entre maiúsculas e minúsculas. Isso significa que permitirá qualquer string, desde que esteja na lista permitida com qualquer esquema de capitalização. Por exemplo, o exemplo acima aceitará Mars
tão facilmente quanto aceitaria mars
. Se necessário, você pode forçar o ValidateSet a ser sensível a maiúsculas e minúsculas usando a opção IgnoreCase
.
A opção IgnoreCase
no ValidateSet, um atributo de validação, determina se os valores fornecidos ao parâmetro correspondem exatamente à lista de valores válidos. Por padrão, IgnoreCase
está definido como $True
(ignorar maiúsculas e minúsculas). Se você definir isso como $False
, fornecer mars como um valor para o parâmetro Planet
em Get-PlanetSize.ps1
geraria uma mensagem de erro.
Você usaria a opção IgnoreCase
atribuindo a ela um valor $true
no final da lista de valores válidos, como mostrado abaixo.
Agora, quando você tenta usar um valor para Planet
que não é exatamente como um valor na lista, a validação falhará.
Usando Complemento de Abas
Outra vantagem de usar ValidateSet é que ele oferece complemento de abas. Isso significa que você pode percorrer os valores possíveis para um parâmetro usando a tecla TAB. Isso melhora muito a usabilidade de um script ou função, especialmente no console.
Nos exemplos abaixo, há algumas coisas a serem observadas:
- O complemento de abas volta ao primeiro valor depois de exibir o último.
- Os valores são apresentados em ordem alfabética, mesmo que não estejam listados no ValidateSet em ordem alfabética.
- Ao digitar uma letra inicial e pressionar TAB, os valores oferecidos pelo complemento de abas são restritos aos que começam com essa letra.


Você também pode aproveitar o complemento de abas ValidateSet no Ambiente de Script Integrado do PowerShell (ISE), conforme mostrado no exemplo abaixo. O recurso de IntelliSense do ISE mostra a você a lista de valores possíveis em uma caixa de seleção agradável.
O IntelliSense retorna todos os valores que contêm a letra que você digita, em vez de apenas aqueles que começam com ela.

Agora que cobrimos os atributos de validação ValidateSet como estão no Windows 5.1, vamos dar uma olhada no que foi adicionado no PowerShell Core 6.1 e ver se isso pode fornecer mais capacidades de validação para nosso script.
Compreendendo as Mudanças no ValidateSet no PowerShell 6.1
Com a chegada do PowerShell Core 6.1, duas novas capacidades foram adicionadas aos atributos de validação ValidateSet:
- A propriedade
ErrorMessage
- Uso de classes em ValidateSet através do acesso ao
System.Management.Automation.IValidateSetValuesGenerator
A propriedade ErrorMessage
A mensagem de erro padrão gerada quando você fornece um nome de planeta incorreto para Get-PlanetSize.ps1 é útil, mas um pouco longa:
Use a propriedade ErrorMessage
do atributo de validação ValidateSet
para definir uma mensagem de erro diferente, como mostrado no exemplo abaixo. {0}
é automaticamente substituído pelo valor enviado e {1}
é automaticamente substituído pela lista de valores permitidos.
Substitua o bloco Param()
no arquivo do script e salve-o. Em seguida, tente novamente Get-PlanetSize.ps1 -Planet Barsoom
. Observe que o erro agora é mais sucinto e descritivo.
Em seguida, dê uma olhada em uma nova maneira de definir os valores aceitáveis em ValidateSet através de uma classe PowerShell classe.
Classes PowerShell
Tipos personalizados, conhecidos no PowerShell como classes, estão disponíveis desde a versão 5. Com a chegada do PowerShell Core 6.1, há um novo recurso que permite o uso de uma classe para fornecer os valores para o ValidateSet.
Usar uma classe permite contornar a principal limitação de um ValidateSet – ele é estático. Ou seja, ele está incorporado como parte da função ou script e só pode ser alterado editando o próprio script.
A nova funcionalidade que funciona com ValidateSet
é a capacidade de usar a classe System.Management.Automation.IValidateSetValuesGenerator. Podemos usar isso como base para nossas próprias classes usando herança. Para trabalhar com ValidateSet
, a classe deve ser baseada em System.Management.Automation.IValidateSetValuesGenerator e deve implementar um método chamado GetValidValues()
.
O método GetValues()
retorna a lista de valores que você deseja aceitar. Um bloco Param()
com a lista estática de planetas substituída por uma classe [Planet]
ficaria assim. Este exemplo ainda não funcionará. Continue lendo para aprender como implementar isso.
Usando uma Classe para uma Lista de Valores ValidateSet: Um Exemplo Real
Para demonstrar o uso de uma classe para uma lista de valores ValidateSet, você vai substituir a lista estática de planetas usada anteriormente por uma lista carregada de um arquivo de texto CSV. Você não precisará mais manter uma lista estática de valores dentro do próprio script!
Criando uma Fonte de Dados para a Classe
Primeiro, você precisará criar um arquivo CSV contendo cada um dos valores válidos. Para fazer isso, copie e cole este conjunto de dados em um novo arquivo de texto e salve-o como planets.csv na mesma pasta que o script Get-PlanetSize.ps1.
Adicionando a Classe ao Script
Qualquer classe usada pelo ValidateSet deve ser definida antes de o ValidateSet tentar usá-la. Isso significa que a estrutura do arquivo Get-PlanetSize.ps1 como está não funcionará.
A classe [Planet]
deve ser definida antes de poder ser usada, então ela deve estar no início do script. Uma definição de classe esqueleto adequada se parece com abaixo:
Dentro do método GetValidValues()
da classe, use o cmdlet Import-CSV
para importar o arquivo de texto planetas.csv criado anteriormente. O arquivo é importado para uma variável com escopo global, chamada $planetas
, para acessá-lo posteriormente no script.
Use o comando return
para retornar a lista de nomes de planetas através de GetValidValues()
. Após essas mudanças, a classe deve agora parecer como abaixo.
Em seguida, remova a declaração da tabela de hash $planetas
do script, como mostrado abaixo. A variável global $planetas
, que é preenchida pela classe [Planet]
, contém os dados do planeta.
Agora envolva o restante do código original em uma função e a chame de Get-PlanetDiameter
para diferenciá-la do nome do script. Coloque o bloco Param()
que estava no início do script dentro da função. Substitua a lista estática de planetas por uma referência à classe [Planet]
, como mostrado abaixo.
$output = "O diâmetro do planeta {0} é {1} km" -f $_, $planets[$_]
substituir pela seguinte duas linhas. Estas permitem que o script procure um planeta no array de objetos criado por Import-CSV
, em vez da tabela de hash que você criou anteriormente e removeu do script:
Após este conjunto de mudanças, seu script final precisa se parecer com isso:
Lembre-se, a partir deste ponto, o script só funciona no PowerShell 6.1 ou posterior
Agora, como você utiliza este script?
Executando o Script
Você não pode usar a nova versão do script diretamente executando o script. Todo o código útil está agora envolvido em uma função. Você precisa dot source o arquivo em vez disso para permitir o acesso à função de dentro da sessão do PowerShell.
Uma vez dot-sourced, agora você tem acesso à nova função Get-PlanetDiameter
na sessão do PowerShell, com autocompletar.
“Qual é o benefício de todo esse trabalho?”, eu ouço você perguntar. “O script parece funcionar da mesma forma, mas é mais difícil usar o código!”
Tente isso:
- Abra o arquivo
planets.csv
que você criou anteriormente. - Adicione uma nova linha com um novo nome e diâmetro.
- Salve o arquivo CSV.
Na mesma sessão em que você inicialmente carregou seu script, tente procurar o diâmetro do novo planeta usando Get-PlanetDiameter
. Funciona!
Usar uma classe dessa maneira nos proporciona vários benefícios:
- A lista de valores válidos agora está separada do próprio código, mas quaisquer alterações nos valores no arquivo são captadas pelo script.
- O arquivo pode ser mantido por alguém que nunca acessa o script.
- A more complex script could look up information from a spreadsheet, database, Active Directory or a web API.
Como você pode ver, as possibilidades são quase infinitas ao usar uma classe para fornecer valores de ValidateSet.
Concluindo
Cobrimos muito terreno enquanto construímos Get-PlanetSize.ps1
, então vamos recapitular.
Neste artigo, você aprendeu:
- O que é um atributo de validação ValidateSet e por que você pode querer usá-lo
- Como adicionar ValidateSet a uma função ou script do PowerShell
- Como o preenchimento automático funciona com ValidateSet
- Como usar a propriedade
IgnoreCase
para controlar se o seu ValidateSet é sensível a maiúsculas e minúsculas - Como usar a propriedade
ErrorMessage
com seu ValidateSet e PowerShell 6.1 - Como usar uma classe para criar um ValidateSet dinâmico com PowerShell 6.1
O que você está esperando? Comece a usar ValidateSet hoje!
Leitura adicional
Source:
https://adamtheautomator.com/powershell-validateset/