Funções PowerShell

Esta entrada é parte 12 de 13 da série Learn PowerShell

Neste episódio da série Learn PowerShell vamos examinar as funções PowerShell. No último episódio cobrimos os scripts PowerShell onde começamos a criar soluções e resolver problemas usando o PowerShell. Os scripts PowerShell são óptimos e muitas pessoas passam bastante tempo nesta fase quando aprendem o PowerShell. Os scripts permitem-lhe manter as coisas bastante simples, e podem ajudá-lo a automatizar rapidamente as tarefas. À medida que você melhora e começa a escrever mais PowerShell você vai precisar procurar criar funções PowerShell!

Video

Se preferir o formato de vídeo em vez da documentação escrita, discuto este tópico no seguinte TechThoughts video:

Quando deve escrever uma função PowerShell

No final do dia um script PowerShell é um conjunto de código que executa uma tarefa. É isso que uma função PowerShell também faz! Então, por que você escolheria escrever uma função versus um script? Nós vamos mergulhar em algumas razões abaixo. De uma maneira geral, um script é algo para você. Quando você quiser começar a compartilhar seu código, ou ter seus colegas de equipe engajados, você vai querer começar a engajar algumas das capacidades que as funções fornecem. Não há uma linha firme. Para uma tarefa rápida que será executada na sua estação de trabalho uma vez, um script pode fazer sentido. Se você estiver escrevendo algum PowerShell que outros possam usar, ou que você possa usar mais de uma vez, uma função provavelmente servirá melhor.

  • Com um único propósito – uma função é tipicamente usada para executar uma tarefa estreita e “faça uma coisa, e faça muito bem”. Isto faz com que as funções sejam altamente reutilizáveis. Se você escrever uma função de registo por exemplo, você pode então usar essa função de registo PowerShell com outras funções ou scripts.
  • Ajuda – funções suportam comentários baseados em ajuda. Isto permite que os seus utilizadores façam coisas como o tipo Get-Help e descubram como usar a sua função.
  • Parâmetros – o suporte para declarações e controlo de parâmetros simples e avançados permite que a sua função seja dinâmica e tome várias formas de entrada do utilizador.
  • Testable – as funções podem ser testadas e ridicularizadas o que melhora muito a qualidade do código.

Anatomia de uma função PowerShell

Aqui está o layout básico e a ordem de uma função PowerShell. Vamos mergulhar em cada uma destas secções abaixo e explorá-las em detalhe.

# function help - (optional but strongly encouraged)# function name# CmdletBinding - (optional)# parameters - (optional)# function logic (optional Begin / Process / End)# return - (optional)function Verb-Noun { param ( ) begin { } process { } end { }}

Ajuda da Função

Quando você incluir ajuda no topo da sua função ela será exibida quando o Get-Help for executado contra a sua função. Esta é uma capacidade poderosa quando outros estão a explorar o seu código. Ao tirar o tempo necessário para criar uma boa Sinopse e Descrição combinada com exemplos sólidos ajudará os outros a entender para que serve a sua função e como usá-la.

Todos os campos de ajuda são opcionais e você pode adicioná-los ou removê-los ao seu gosto. Eu recomendo que você inclua pelo menos os campos abaixo no mínimo.

<#.SYNOPSIS Short description.DESCRIPTION Long description.EXAMPLE C:\PS> Example of how to use this cmdlet.EXAMPLE C:\PS> Another example of how to use this cmdlet.PARAMETER InputObject Specifies the object to be processed. You can also pipe the objects to this command..OUTPUTS Output from this cmdlet (if any).NOTES General notes.COMPONENT The component this cmdlet belongs to#>

CmdletBinding


Quando você escreve uma grande função e lhe dá um nome como Get-AllFileInformation, ela se parece e agirá como um cmdlet. Mas é uma distinção importante que uma função PowerShell não é uma cmdlet. Cmdlet’s são escritas e compiladas em C# e a sua função PowerShell é escrita em PowerShell.

CmdletBinding é um atributo de funções que permite capacidades que as fazem funcionar mais como cmdlets compiladas. Adicionando isto ao topo da sua função irá dar à sua função um monte de capacidades adicionais como:

  • Write-Verbose – permitir que os usuários usem o switch -Verbose para ver o que sua função está fazendo enquanto ela está fazendo.
  • ShouldProcess – se a sua função vai fazer uma mudança em um sistema que é de alto risco, você pode querer que o usuário confirme a ação.
  • PositionalBinding – permite que a sua função seja executada sem fornecer explicitamente o nome de cada parâmetro. Os valores podem ser inferidos pela ordem em que são fornecidos à sua função

parâmetros

param ( $City, $Units = 'USCS', $Language = 'en', $Short)

Parâmetros servem para fornecer ao usuário uma forma de interagir dinamicamente com a sua função. Você pode assumir várias formas de entrada e realizar uma grande variedade de verificações e validações para garantir que você está recebendo o tipo certo de informação.

Você pode ficar muito básico e declarar apenas os nomes dos seus parâmetros. Alternativamente, você pode ser muito específico sobre o que é necessário para os seus parâmetros:

  • Se o parâmetro é obrigatório
  • A posição de um parâmetro (a ordem)
  • O tipo de parâmetro (string/int/bool/etc)
  • Definir valores padrão
  • Validação de entrada
  • Conjuntos de parâmetros
  • Muito mais

Este post não pode cobrir todas as configurações de parâmetros possíveis. Mesmo depois de anos a escrever PowerShell tenho dificuldade em memorizar todas as configurações e sintaxe dos parâmetros. Saiba que as declarações de parâmetros são a sua forma de levar a entrada na sua função. Você pode fornecer muitos detalhes e controles para eles, ou simplesmente mantê-los simples, dependendo de suas necessidades. Marque os links dos parâmetros no final deste post. Ainda hoje, eu os visito frequentemente!

Begin Process End

Estas três palavras-chave são fases que você pode declarar dentro da sua função.

  • Begin irá inicializar alguns passos no início
  • Process irá processar cada objeto como recebido
  • End pode realizar uma limpeza.

Isto é especialmente útil se você quiser que sua função suporte entradas de processamento do pipeline.

Isto pode ser difícil de entender em teoria, então aqui está um exemplo que demonstra seu uso.

function Get-PipelineBeginEnd { param ( $SomeInput ) begin { "Begin: The input is $SomeInput" } process { "The value is: $_" } end { "End: The input is $SomeInput" }}#Get-PipelineBeginEnd1, 2, 3 | Get-PipelineBeginEnd -SomeInput 'Test'

Quando você executar o código acima, note que o Início é executado uma vez, assim como o Fim. Process é executado para cada item passado para ele e Process tem acesso ao objeto atual no pipeline.

Function Logic

A lógica contida dentro de uma função PowerShell não é diferente da lógica de um script. Aqui é onde você irá escrever a lógica central que executa a tarefa para a qual sua função está destinada. Isto foi abordado nos episódios 1-10 deste curso. Você também pode ver um exemplo completo ao vivo no episódio PowerShell Scripts.

Retorno da função

Nem todas as funções retornam algo quando executadas. Se a sua função irá retornar algo, você pode opcionalmente usar return. Tenha em mente que ao usar return, todas as outras ações na função irão parar e a função irá terminar.

function Get-Total { param ( $Number1, $Number2 ) $total = $Number1 + $Number2 return $total}Get-Total -Number1 2 -Number2 2

No exemplo acima esta simples função contém dois parâmetros do tipo integer. A lógica da função adiciona os dois números juntos e retorna o inteiro ao usuário.

Sua primeira função PowerShell

Veja a função PowerShell abaixo. Note que o layout adere ao que já cobrimos anteriormente. Note também que a seção de ajuda fornece uma grande quantidade de detalhes quanto ao propósito e uso da função.

<#.SYNOPSIS Returns your public IP address..DESCRIPTION Queries the ipify Public IP Address API and returns your public IP..EXAMPLE Get-PublicIP Returns the public IP..OUTPUTS System.String.NOTES https://github.com/rdegges/ipify-api#>function Get-PublicIP { $uri = 'https://api.ipify.org' try { $invokeRestMethodSplat = @{ Uri = $uri ErrorAction = 'Stop' } $publicIP = Invoke-RestMethod @invokeRestMethodSplat } catch { Write-Error $_ } return $publicIP}#Get-PublicIP

Como a lógica real desta função é bastante simples, pode ser tentador deixá-la como um script. Note que isto faz uma coisa específica, e fá-lo bem. Agora você poderia incorporar esta função em outra lógica avançada, ao invés de ter que referenciar ou importar um script. Outros usuários em seu ambiente também podem começar a incorporar esta função assim que se familiarizarem com ela.

Escopo da Função

Como a maioria das linguagens, PowerShell tem regras de escopo para variáveis. Quando uma variável está dentro de uma função você não será mais capaz de “ver” seu valor. Aqui está um exemplo deste comportamento:

function Get-NumberTimesTwo { param ( $Number ) $total = $Number * 2 return $total}#Get-NumberTimesTwoGet-NumberTimesTwo -Number 2

A função comporta-se como esperado e irá multiplicar correctamente um número por dois. No seu console, porém, tente ver qual é o valor de $total. Você não será capaz. Isto é porque $total é escopado para a função, e não para a sua sessão de console ativa.

Isto pode ser confuso para pessoas novas no PowerShell e pode tornar a escrita de funções mais difícil. Existem algumas estratégias para lidar com isso.

Você poderia escrever a maioria de sua lógica em um formato do tipo script, testando variáveis conforme você vai. Uma vez que você esteja confiante que a lógica está funcionando como pretendido, você poderia então embrulhar a lógica dentro de uma função.

Alternativamente, você pode usar Write-Host, Write-Output, ou melhor ainda Write-Debug para ver o que está acontecendo com suas variáveis dentro de sua função!

function Get-NumberTimesTwo { param ( $Number ) $total = $Number * 2 Write-Debug $total return $total}#Get-NumberTimesTwoGet-NumberTimesTwo -Number 2 -Debug

Note que com a chave de debug nós temos acesso ao valor dentro de $total para garantir que nossa lógica está fazendo o que pretendemos.

Exemplo de Fechamento

Aqui está um exemplo maior de fechamento de duas funções PowerShell que lhe permitirá navegar no popular site reddit usando PowerShell!

Visitar o link GitHub gist abaixo para acessar o código e carregá-lo em seu console.

https://gist.github.com/techthoughts2/cd2b720c9b291510cbd643e6ca73e05f

Como você explora estas funções tente responder as seguintes questões:

  • Das duas funções, qual delas é a função primária?
  • São estas funções padrão ou avançadas?
  • Que função vai suportar a entrada do pipeline?

Additional Reading

  • Functions
  • Parameters
  • Functions Advanced
  • Functions Advanced Parameters
  • PowerShell Approved Verbs
  • CmdletBindingAttribute

Series Navigation << PowerShell ScriptsManage Cloud with PowerShell >>