Windows PowerShell: O ciclo de vida de função avançada

Funções avançadas de Windows PowerShell — denominados cmdlets de Script — pode ser um pouco confuso, mas aqui está uma maneira para direcionar suas funções de instalação e limpeza.

Don Jones

Houve um ponto de andamento da confusão para um número de alunos em algumas das minhas classes de Windows PowerShell no local. Espero que explorá-la mais detalhadamente aqui ajudará desenrolar alguma confusão bem para você. O tópico é as funções avançadas de Windows PowerShell, conhecida informalmente como script cmdlets. O modelo para esse tipo de função tem esta aparência:

Function Do-Something { [CmdletBinding()] param( [Parameter(Mandatory=$True, ValueFromPipeline=$True)] [string[]]$computername ) BEGIN {} PROCESS {} END {} }

Existem alguns aspectos confusos para esses cmdlets. Por exemplo, nesse caso, há um parâmetro de entrada definido chamado computername. Isso pode aceitar a entrada do pipeline. Isso significa que você pode chamar esta função de duas maneiras distintas. Primeiro, você pode ter cadeias de caracteres enviada por pipe para ele, como um arquivo de texto que contém um nome de computador por linha:

Get-Content names.txt | Do-Something

Você pode também simplesmente ter um ou mais nomes de computador passaram diretamente para o parâmetro, sem usar o pipeline em todos os:

Do-Something –computername SERVER1,SERVER2

No primeiro exemplo, o bloco de BEGIN da função é executado primeiro. Em seguida, o bloco PROCESS é executado uma vez para cada nome de computador canalizados. A variável de nome_do_computador $ contém apenas um nome de computador ao mesmo tempo. Finalmente, depois que todos eles estão processados, o bloco END é executado uma vez.

No segundo exemplo, os blocos BEGIN e END nunca são executados. O bloco PROCESS é executado apenas uma vez e nome_do_computador $ contém cada nome que foi passado ao parâmetro.

Essa diferença extreme no comportamento pode tornar difícil de instalação e as tarefas de limpeza que são executados em ambas as situações. Ele também pode causar confusão sobre como lidar com os parâmetros de nome_do_computador $. No primeiro exemplo contém apenas um valor por vez, enquanto o segundo, ele conterá um ou mais valores, dependendo de qual foi dado ao parâmetro – ComputerName. Você pode resolver o problema de nome_do_computador $, simplesmente colocar um loop ForEach dentro do bloco de processo:

Function Do-Something { [CmdletBinding()] param( [Parameter(Mandatory=$True, ValueFromPipeline=$True)] [string[]]$computername ) BEGIN {} PROCESS { Foreach ($computer in $computername) { # use $computer here } } END {} }

Essa técnica garante que a variável $computer conterá apenas um nome de computador por vez, portanto, é melhor trabalhar com o que, em vez dos computername $.

A instalação e limpeza é um pouco mais complicado. Você não quiser fazer a instalação diretamente no bloco de processo. Esse bloco pode executar várias vezes quando objetos forem canalizados. Por outro lado, você não pode colocar a instalação diretamente para o bloco BEGIN. Que não será executada se nada canalizado. Obviamente, existem muitas maneiras que você poderia lidar com isso, mas isso parece ser o melhor:

Function Do-Something { [CmdletBinding()] param( [Parameter(Mandatory=$True, ValueFromPipeline=$True)] [string[]]$computername ) BEGIN { $setup_done = $false function DoSomethingSetup { set-variable -name setup_done -value $true -scope 1 } DoSomethingSetup } PROCESS { if (-not $setup_done) { DoSomethingSetup } Foreach ($computer in $computername) { # use $computer here } } }

Isso tira proveito do fato de que todos os blocos BEGIN, processo e END compartilham um escopo comum, significando que eles compartilham as mesmas variáveis. Definindo uma variável como um sinalizador, você pode ter certeza o conteúdo da chave do bloco BEGIN — minha função DoSomethingSetup — chamado somente uma vez.

Observe o "DoSomethingSetup" função possui para usar uma técnica especial para definir o sinalizador como $True uma vez você concluiu as tarefas de configuração. Porque é uma função, o DoSomethingSetup tem seu próprio escopo. Normalmente, ele não é possível alterar o valor de uma variável de fora desse escopo. Você pode modificar explicitamente a variável necessária usando o cmdlet Set-Variable.

Realizando o truque mesmo para as tarefas de limpeza é um pouco mais difícil. No primeiro exemplo, onde os objetos estão sendo canalizados para fazer algo, o bloco END será executado. Lá você poderia colocar apenas as tarefas de limpeza. No entanto, no segundo exemplo onde nada canalizado, final nunca será executado. O bloco PROCESS será executado apenas uma vez, portanto ele não necessariamente "sabe" que o bloco END não está prestes a executar.

Não é possível apenas ter o bloco de processo chamar uma função dentro do bloco final. Quando objetos forem canalizados, o bloco PROCESS será executado várias vezes — e você não deseja ter que chamar o bloco final várias vezes.

Existem algumas maneiras dissimuladas para solucionar o problema, mas a abordagem mais simples é geralmente a melhor: quando você precisar de algum tipo de atividade de limpeza (como fechar uma conexão de banco de dados), esquecer sobre como usar os blocos BEGIN e END completamente. Ter o bloco PROCESS presumir que ele só será executado uma vez e basta colocar todos os programa de instalação e limpeza de lá.

Ele pode ser um pouco desperdício — ele pode ser abrindo e fechando uma conexão de banco de dados repetidamente, por exemplo — mas ele é eficaz. Ele também elimina a necessidade de ter perambulations estranhas e difícil de seguir dentro de seu código.

Essas funções para manipular pipeline e cenários de pipeline não programação podem ser complicada. Em algumas colunas futuras, vamos compartilhar algumas das maneiras de que outras colegas solucionou esse problema, assim você terá diferentes opções para usar em seu próprio ambiente.

Denny Cherry

Don Jones é um destinatário de prêmio de MVP da Microsoft e autor de "Aprender Windows PowerShell em um mês de almoços" (Manning publicações co, 2010), um catálogo criado para ajudar a qualquer administrador se tornam efetivas com Windows PowerShell. Jones também oferece treinamento de Windows PowerShell público e no local. Entre em contato com ele por meio de seu site em ConcentratedTech.com.

Conteúdo relacionado