Quando você está escrevendo um script ou função em 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 podem aceitar, não poderá garantir que não haverá situações em que valores inadequados são fornecidos. Neste artigo, aprenda como usar o atributo de validação de parâmetro ValidateSet no PowerShell para limitar esses valores apenas aos que você define.
Ao escrever um script ou função em PowerShell, você pode usar vários 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 o ValidateSet faz, por que você pode querer usar ValidateSet em seu código e como fazê-lo. Você também aprenderá sobre o recurso de conclusão de guias habilitado pelo ValidateSet, que ajudará os usuários do seu código a fornecer valores válidos para os parâmetros.
PowerShell ValidateSet: Uma breve visão geral
ValidateSet é um atributo de parâmetro que permite que você defina um conjunto de elementos que são aceitos apenas como o valor para aquele parâmetro.
Por exemplo, talvez você tenha um script definido para trabalhar 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á razão para que o usuário possa usar “foobar” como valor quando você sabe de antemão quais valores o script precisa. ValidateSet proporciona essa capacidade.
Requisitos
Este artigo será um passo a passo de aprendizagem. Se você planeja acompanhar, precisará do seguinte:
- Visual Studio Code ou qualquer outro editor de código. Estarei usando o Visual Studio Code.
- Pelo menos PowerShell 5.1 para a maioria do código neste artigo. Há uma seção que requer PowerShell 6.1 ou posterior e identificarei isso 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 e facilitará a descoberta de seus possíveis valores de parâmetros.
Começando
Para começar, primeiro copie e cole o código PowerShell abaixo em 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 de todos os planetas são retornadas, mesmo que você queira apenas as informações de Marte.
Talvez você queira a capacidade de especificar um único planeta em vez de retornar todos eles. Você faria 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 Planeta
. Um bloco Param()
adequado fica assim:
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 Planeta
ao script é alterar a linha $planets.keys | Foreach-Object {
para $Planeta | Foreach-Object {
. Agora você não está mais dependendo do hashtable definido estaticamente anteriormente e sim lendo o valor do parâmetro Planeta
.
Agora, se você executar o script e especificar um planeta usando o parâmetro Planeta
, você verá apenas informações sobre aquele planeta específico.
Excelente. Script concluído? Talvez não.
As Opções estã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 um valor válido ou não. O script precisa de uma maneira de limitar quais valores são aceitos para o parâmetro Planeta
. 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 Planeta
. Agora, uma mensagem de erro útil é retornada. A mensagem é específica sobre o que deu errado e até mesmo 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 é insensível a maiúsculas e minúsculas. Isso significa que ele permitirá qualquer string, desde que esteja na lista permitida com qualquer esquema de capitalização. Por exemplo, o exemplo acima aceitará Marte
tão facilmente quanto aceitaria marte
. 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
em 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
é definido como $True
(ignorar maiúsculas e minúsculas). Se você definir isso como $False
, fornecer marte como um valor para o parâmetro Planeta
para Get-PlanetSize.ps1
geraria uma mensagem de erro.
Você usaria a opção IgnoreCase
atribuindo-lhe 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 igual a um valor na lista, a validação falhará.
Usando a Complementação de Tabulação
Outra vantagem de usar o ValidateSet é que ele oferece complementação de tabulação. Isso significa que você pode percorrer os valores possíveis para um parâmetro usando a tecla TAB. Isso melhora significativamente a usabilidade de um script ou função, especialmente no console.
Nos exemplos abaixo, há algumas coisas a serem observadas:
- A complementação de tabulação retorna ao primeiro valor após exibir o último.
- Os valores são apresentados em ordem alfabética, mesmo que não estejam listados no ValidateSet de forma alfabética.
- Digitar uma letra inicial e pressionar TAB restringe os valores oferecidos pela complementação de tabulação para aqueles que começam com essa letra.


Você também pode aproveitar a complementação de tabulação do ValidateSet no Ambiente de Scripting Integrado do PowerShell (ISE), como mostrado no exemplo abaixo. A função Intellisense do ISE mostra 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 do ValidateSet conforme 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 Alterações 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 a
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 de script e salve-o. Em seguida, tente Get-PlanetSize.ps1 -Planet Barsoom
novamente. Note abaixo que o erro é muito menos longo e mais descritivo.
Em seguida, dê uma olhada em uma nova maneira de definir os valores aceitáveis em ValidateSet via PowerShell classe.
Classes do 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 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 trabalha 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.
Usar 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 planetas.csv na mesma pasta que o script Get-PlanetSize.ps1.
Adicionando a Classe ao Script
Qualquer classe usada por ValidateSet deve estar definida antes de ValidateSet tentar usá-la. Isso significa que a estrutura de 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 esquelética adequada se parece com o seguinte:
Dentro do método GetValidValues()
da classe, use o cmdlet Import-CSV
para importar o arquivo de texto planets.csv criado anteriormente. O arquivo é importado para uma variável com escopo global, chamada $planets
, para acessá-lo posteriormente no script.
Use a instrução return
para retornar a lista de nomes de planetas via GetValidValues()
. Após essas alterações, a classe deve parecer agora como abaixo.
Em seguida, remova a declaração do hash table $planets
do script, como mostrado abaixo. A variável global $planets
, que é populada pela classe [Planet]
, contém os dados do planeta em vez disso.
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]
, conforme mostrado abaixo.
Substitua a linha $output = "O diâmetro do planeta {0} é {1} km" -f $_, $planets[$_]
pelas duas linhas seguintes. Elas permitem que o script pesquise um planeta no array de objetos criado por Import-CSV
, em vez da tabela 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ê usa este script?
Executando o Script
Você não pode usar a nova versão do script diretamente apenas executando o script. Todo o código útil está agora envolto em uma função. Você precisa importar o arquivo em vez disso para permitir o acesso à função dentro da sessão do PowerShell.
Uma vez importado, agora você tem acesso à nova função Get-PlanetDiameter
na sessão do PowerShell, com preenchimento de tabulação.
“Qual é o benefício de todo esse trabalho?”, eu ouço você perguntar. “O script parece funcionar da mesma maneira, mas é mais difícil de 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ê originalmente carregou seu script usando “dot source”, tente procurar o diâmetro do novo planeta usando `Get-PlanetDiameter
`. Funciona!
Usar uma classe dessa maneira nos oferece vários benefícios:
- A lista de valores válidos agora está separada do código em si, mas quaisquer alterações nos valores no arquivo são capturadas 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 bastante terreno ao construir 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 PowerShell ou script
- Como funciona o preenchimento automático 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/