Olá pessoal, tudo bem? Espero que sim!
No último post falamos sobre as Funções (Functions) do Powershell, como críá-las e instalá-las para uso contínuo em seu shell. Hoje vamos continuar neste tema falando sobre os atributos que podemos trabalhar com as Funções.
Basicamente os atributos disponíveis para uma Função são: Nomes, Parâmetros, Pipeline, Filtros, Escopo e Ajuda.
Devido a extensão do conteúdo, no post de hoje irei abordar Nomes e os Parâmetros que podem ser criados para Funções.
Atribuindo Nomes a Funções
No último post observamos o exemplo da Função personalizada Get-ArquivosAreaDeTrabalho. Quando falamos sobre a construção de nome para uma Função, precisamos ficar atentos nas melhores práticas para compor a sua estrutura. Como a própria Microsoft orienta:
As funções devem usar os verbos padrão que foram aprovados para todos os comandos do PowerShell. Esses verbos nos ajudam a manter nossos nomes de comandos simples, consistentes e fáceis para os usuários entenderem.
A criação de comandos para funções seguindo a estrutura “verbo-substantivo” não é uma regra, não sendo obrigatório seu uso, mas se trata de uma questão de boa prática principalmente se você tem a intenção de disponibilizar seu script em um repositório público.
Relembrando:
Sintaxe: Function <comando> { cadeia de comandos }
Exemplos:
1 2 3 4 5 6 7 8 9 |
# Verificar existência de pasta "Teste" na Area de Trabalho PS C:\Users\RobotChicken> Function TestarPastaAreaDeTrabalho {Test-Path -Path C:\Users\RobotChicken\Desktop\Teste} PS C:\Users\RobotChicken> TestarPastaAreaDeTrabalho True PS C:\Users\RobotChicken> Function Test-PastaAreaDeTrabalho {Test-Path -Path C:\Users\RobotChicken\Desktop\Teste} PS C:\Users\RobotChicken> Test-PastaAreaDeTrabalho True |
Atribuindo Parâmetros a Funções
Você pode adicionar parâmetros personalizados para exponenciar a utilização de uma Função. Os parâmetros sempre são representados como variáveis, sendo iniciados por $.
Exemplo: $nomedoparâmetro.
Os parâmetros podem ser: Nomeados, Posicionais e de Alternância.
Parâmetros Nomeados
São parâmetros onde você pode declarar qualquer valor baseado no tipo indicado para atribuir um valor a uma variável que será usada no processamento da Função.
Sintaxe: Function <comando> {
Param ([type]$parametro, [type]$parametro2)
<cadeia de comandos>
}
ou
Function <comando> [([type]$parametro1, [type]$parametro2)] { <cadeia de comando> }
Exemplo:
Considere a seguinte Função:
1 2 3 |
Function Listar-AreaDeTrabalho {param([int]$NumeroRetorno) Get-ChildItem -Path C:\Users\RobotChicken\Desktop | Select -First $NumeroRetorno } |
O resultado será este:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# Listar arquivos da área de trabalho controlando a quantidade de arquivos que serão exibidos PS C:\Users\RobotChicken> Listar-AreaDeTrabalho -NumeroRetorno 1 Diretório: C:\Users\RobotChicken\Desktop Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 16/06/2019 11:06 Teste PS C:\Users\RobotChicken> Listar-AreaDeTrabalho -NumeroRetorno 2 Diretório: C:\Users\RobotChicken\Desktop Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 16/06/2019 11:06 Teste d----- 16/06/2019 11:28 Teste2 PS C:\Users\RobotChicken> Listar-AreaDeTrabalho -NumeroRetorno 3 Diretório: C:\Users\RobotChicken\Desktop Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 16/06/2019 11:06 Teste d----- 16/06/2019 11:28 Teste2 -a---- 16/06/2019 12:22 420 alias-cont-md.csv |
No exemplo acima, usei o parâmetro $NumeroRetorno para indicar o número de linhas que o comando Get-ChildItem retornaria da minha Área de Trabalho.
Tipos de Valores para Parâmetros
Quando declaramos um parâmetro, por uma questão de boas práticas, devemos sempre indicar qual tipo de valor será atribuído a este. Os tipos de valores disponíveis basicamente são:
[int] | Inteiro assinado de 32 bits |
[long] | Inteiro assinado de 64 bits |
[string] | Cadeia de comprimento fixo de caracteres Unicode |
[char] | Caractere Unicode de 16 bits |
[bool] | Valor Verdadeiro ou Falso |
[byte] | Inteiro não assinado de 8 bits |
[double] | Número de ponto flutuante de precisão dupla de 64 bits |
[decimal] | Valor decimal de 128 bits |
[single] | Número de ponto flutuante de 32 bits de precisão simples |
[array] | Matriz de valores |
[xml] | Objeto de Documento XML |
[hashtable] | Objeto Hashtable (semelhante a um objeto Dicionário) |
Você não é obrigado a especificar o tipo de valor do parâmetro, contudo, atribuir o tipo de parâmetro vai prevenir eventuais falhas na execução da função quando passado um valor não aceito para os comandos especificados.
Exemplo:
1 2 3 4 5 6 7 8 |
PS C:\Users\RobotChicken> Listar-AreaDeTrabalho -NumeroRetorno X Listar-AreaDeTrabalho : Não é possível processar a transformação do argumento em parâmetro 'NumeroRetorno'. Não é possível converter o valor "X" para o tipo "System.Int32". Erro: "A cadeia de caracteres de entrada não estava em um formato correto." No linha:1 caractere:38 + Listar-AreaDeTrabalho -NumeroRetorno X + ~ + CategoryInfo : InvalidData: (:) [Listar-AreaDeTrabalho], ParameterBindingArgumentTransformationException + FullyQualifiedErrorId : ParameterArgumentTransformationError,Listar-AreaDeTrabalho |
Conforme o exemplo acima, se eu especificar o valor “X“, que é um tipo de cadeia de comprimento fixo de caracteres Unicode (string), a minha função não foi executada com sucesso e na saída, recebi a informação que não se trata do tipo de valor de parâmetro aceitável para a operação.
Parâmetros Posicionais
Este tipo de parâmetro não tem valor declarado, mas indica qual a posição que um valor será retornado ou atribuído. O parâmetro posicional é representado pela variável de ambiente do Powershell $args[posição], e a posição indica em qual quadrante o dado desejado está.
Exemplo:
Considere a seguinte Função:
1 2 3 |
Function Get-ExtensaoArquivos {$args = $args.Split(".") $extensao = $args[1] $extensao} |
Resultado:
1 2 3 4 |
PS C:\Users\RobotChicken\Desktop> Get-ExtensaoArquivos arquivo.TesteDeExtensao TesteDeExtensao PS C:\Users\RobotChicken\Desktop> Get-ExtensaoArquivos arquivo.txt.TesteDeExtensao txt |
Como puderam observar, na função utilizei o operador Split e indiquei que a variável de ambiente Powershell $args era para ser dividida em partes toda vez que fosse encontrado um “.“. A partir dai, o valor indicado vai ser separado em partes indicadas por números dentro de colchetes ([]), posicionando os quandrantes da esquerda para a direita em números iniciados em 0.
Então, quando eu digo que a variável $extensao = $args[1], estou dizendo que a variável extensao, vai armazenar a segunda parte dividida do valor que digitei como parâmetro da função. Desta forma, após a divisão do primeiro exemplo de execução da Função, os quadrantes de argumentos ficaram da seguinte forma:
$arg[0] = arquivo; $arg[1] = TesteDeExtensão
No segundo exemplo, usei o arquivo “arquivo.txt.TesteDeExtensao“, cujo valor retornado foi “txt“. Isto ocorreu, pois, como existe a operação de divisão baseado no caractere “.” e o valor $args[1] foi definido para a variável $extensao, os quadrantes ficaram da seguinte forma:
$arg[0] = arquivo; $arg[1] = txt; $arg[2] = TesteDeExtensao
Desta forma, podemos utilizar os parâmetros posicionais para diversas finalidades, seja para retornar uma posição de um determinado valor ou atribuir um valor a determinada posição do parâmetro especificado, entre diversas outras aplicações.
Parâmetros de Alternância
Este tipo de parâmetro assim como os parâmetros posicionais não requer um valor declarado. São utilizados para alternar ações previamente configuradas na função para serem realizadas. As alternâncias são definidas utilizando o type [switch]<nome do parâmetro>
Exemplo:
Considere a Função:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
Function Alternar-ExistenciaArquivo {param ([switch]$criar, [switch]$excluir) If ($criar) { # Declara as mensagens de retorno $msg1 = "O arquivo printf.txt não existe. Criando o arquivo..." $msg2 = "O arquivo printf.txt foi criado com sucesso" $msg3 = "Não foi possível criar o arquivo printf.txt" $msg4 = "O arquivo printf.txt já existe." # Declara o caminho do arquivo $arquivo = "C:\Users\RobotChicken\Desktop\printf.txt" # Verifica se o arquivo existe, se não existir, cria o arquivo. $validacao = Get-Item $arquivo -ErrorAction SilentlyContinue If($validacao){Write-Host -ForegroundColor Yellow $msg4} Else{Write-Host -ForegroundColor Yellow $msg1 New-Item "C:\Users\RobotChicken\Desktop\printf.txt" If ($arquivo){Write-Host -ForegroundColor Green $msg2} Else {Write-Host -ForegroundColor Red $msg3}} } # Remove o arquivo ElseIf($excluir) {Remove-Item "C:\Users\RobotChicken\Desktop\printf.txt" -Force -ErrorAction SilentlyContinue Write-Host -ForegroundColor Red "O arquivo printf.txt foi excluído."} # Não realiza nenhuma operação e informa Else{Write-Host -ForegroundColor Yellow "Nenhum parâmetro foi definido. Nenhuma ação foi executada."} } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
PS C:\Users\RobotChicken\Desktop> Alternar-ExistenciaArquivo Nenhum parâmetro foi definido. Nenhuma ação foi executada. PS C:\Users\RobotChicken\Desktop> Alternar-ExistenciaArquivo -criar O arquivo printf.txt já existe. PS C:\Users\RobotChicken\Desktop> Alternar-ExistenciaArquivo -excluir O arquivo printf.txt foi excluído. PS C:\Users\RobotChicken\Desktop> Alternar-ExistenciaArquivo -criar O arquivo printf.txt não existe. Criando o arquivo... Diretório: C:\Users\RobotChicken\Desktop Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 22/06/2019 14:26 0 printf.txt O arquivo printf.txt foi criado com sucesso |
Ok, acredito que eu tenha me empolgado um pouco neste exemplo, risos. Basicamente no exemplo acima, criamos uma Função que ao ser invocada com o parâmetro -criar, verifica a existência de um arquivo predefinido na própria Função e caso ele não exista, este parâmetro garantirá a sua criação. Ao usar o parâmetro -excluir, a Função remove o arquivo predefinido. Se não passarmos algum parâmetro, o script retornará que esta função necessita de um parâmetro definido para funcionar corretamente.
Para fazer isto, declarei os parâmetros [switch]$criar e [switch]$excluir no início da função e em seguida, utilizei os operadores lógicos If, ElseIf e Else para condicionar a ação de acordo com o parâmetro escolhido. No português claro, se eu passei o parâmetro -criar, a Função irá atender aos critérios especificados no bloco If[Se]($criar), se passar o parâmetro -excluir, será atendido os critérios do bloco ElseIf[Ao contrário, se]($excluir), ou se não passar algum parâmetro, será atendido os comandos no bloco Else[Ao contrário].
Vamos deixar este exemplo mais interessante, incluindo um parâmetro tipo [string]$caminhoarquivo, onde irei referenciar o caminho do arquivo a ser criado ou excluído:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
Function Alternar-ExistenciaArquivo {param ([switch]$criar, [switch]$excluir, [string]$caminhoarquivo) If ($criar) { # Declara as mensagens de retorno $msg1 = "O arquivo $caminhoarquivo não existe. Criando o arquivo..." $msg2 = "O arquivo $caminhoarquivo foi criado com sucesso" $msg3 = "Não foi possível criar o arquivo $caminhoarquivo" $msg4 = "O arquivo $caminhoarquivo já existe." # Declara o caminho do arquivo $arquivo = $caminhoarquivo # Verifica se o arquivo existe, se não existir, cria o arquivo. $validacao = Get-Item $arquivo -ErrorAction SilentlyContinue If($validacao){Write-Host -ForegroundColor Yellow $msg4} Else{Write-Host -ForegroundColor Yellow $msg1 New-Item $caminhoarquivo If ($arquivo){Write-Host -ForegroundColor Green $msg2} Else {Write-Host -ForegroundColor Red $msg3}} } ElseIf($excluir) {Remove-Item $caminhoarquivo -Force Write-Host -ForegroundColor Red "O arquivo $caminhoarquivo foi excluído."} Else{Write-Host -ForegroundColor Yellow "Nenhum parâmetro de ação foi definida. Nenhuma ação foi executada."} } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
PS C:\Users\RobotChicken\Desktop> Alternar-ExistenciaArquivo -caminhoarquivo C:\Users\RobotChicken\Desktop\printf-novo.txt -criar O arquivo C:\Users\RobotChicken\Desktop\printf-novo.txt não existe. Criando o arquivo... Diretório: C:\Users\RobotChicken\Desktop Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 22/06/2019 14:45 0 printf-novo.txt O arquivo C:\Users\RobotChicken\Desktop\printf-novo.txt foi criado com sucesso PS C:\Users\RobotChicken\Desktop> Alternar-ExistenciaArquivo -caminhoarquivo C:\Users\RobotChicken\Desktop\printf-novo.txt -excluir O arquivo C:\Users\RobotChicken\Desktop\printf-novo.txt foi excluído. PS C:\Users\RobotChicken\Desktop> Alternar-ExistenciaArquivo -caminhoarquivo C:\Users\RobotChicken\Desktop\printf-novo.txt Nenhum parâmetro foi definido. Nenhuma ação foi executada. |
Adicionando o parâmetro $caminhoarquivo, não ficamos preso somente ao arquivo especificado dentro da Função, então podemos realizar com esta Função a operação de criar e excluir quaisquer arquivos no computador.
Ainda não entendeu como funciona os parâmetros de alternância? Vamos para um exemplo bem mais simples:
1 2 3 4 |
Function Ligar-Luz {param ([switch]$ligar) If ($ligar) {Write-Host -ForegroundColor Green "Luz Ligada"} Else {Write-Host -ForegroundColor Red "Luz Desligada"} } |
1 2 3 4 5 |
PS C:\Users\RobotChicken\Desktop> Ligar-Luz -ligar Luz Ligada PS C:\Users\RobotChicken\Desktop> Ligar-Luz Luz Desligada |
Na Função acima trabalhamos com a metáfora “Ligar-Luz” (nome da Função) . Se utilizarmos o parâmetro de alternância $ligar, o script retornará a mensagem de “Luz Ligada“. Se eu não especificar este parâmetro, o retorno será a mensagem “Luz Desligada“. Poderíamos também trabalhar da mesma maneira que o exemplo anterior, onde eu poderia colocar um parâmetro $desligar e incluir mais um If para indicar a mensagem de desligamento da luz, mas acredito que a esta altura, você finalmente já dominou este tipo de parâmetro, então seria redundante abrir mais exemplos.
Conclusão
A utilização de parâmetros em funções é extremamente útil na hora de criar scripts Powershell. Eles permitem flexibilizar o poder de atuação da Função e permite uma maior abrangência no escopo do script, quando corretamente parametrizado. Não é uma via de regra utilizá-los, mas procure ter em mente que especificando-os, você poderá recortar uma Função personalizada em partes e poderá utilizar somente o necessário no contexto desejado.
É isso aí galera, por hoje é só. Até o próximo post!
Dúvidas, sugestões, críticas? Entre em contato aqui!
Gostou? Deixe seu comentário e não se esqueçam de curtir a página do Facebook na barra lateral!