Share via


O Windows PowerShell: Transforme um comando em uma ferramenta reutilizável

Você pode reempacotar e reutilizar seus esforços quando se trata dos comandos e cmdlets do Windows PowerShell.

Don Jones

Não importa como inexperientes estiver com o Windows PowerShell quando você começar a trabalhar com ele, sempre há muito espaço para crescimento. Você pode começar executando comandos simples, trabalhar até aos comandos mais complicado e eventualmente remontar esses comandos em algo que olha e sente quase como um cmdlet nativo. Estes são chamados de funções avançadas e informalmente conhecidos como "cmdlets do script".

Considere uma situação onde você poderá recuperar alguma informação de inventário crítico de um computador. Você precisa da versão do Windows, número de série do BIOS, service pack versão e processador de arquitetura. Você pode obter essas informações com esses três comandos:

Get-WmiObject –class Win32_OperatingSystem –computername SERVER-R2 | Select-Object –property __SERVER,BuildNumber,Caption,ServicePackMajorVersion
Get-WmiObject –class Win32_BIOS –computername SERVER-R2 | Select-Object –property SerialNumber
Get-WmiObject –class Win32_Processor –computername SERVER-R2 | Select-Object –property AddressWidth

O problema é que esses comandos geram três conjuntos de resultados diferentes. Você diretamente não é possível canalizar tudo o que fora para um único arquivo CSV, por exemplo, para armazenar os dados de inventário, ou um único arquivo HTML para exibir o inventário como uma página da Web. É preferível para agrupar os dados em um único comando com parâmetros que ainda poderia usar um usuário menos experientes. Você precisa do comando para:

  • Aceite um ou mais nomes de computador como seqüências de caracteres de pipeline, como em:
Get-Content names.txt | Get-OSInfo | ConvertTo-HTML | Out-File info.html
  • Aceite um ou mais nomes de computador em um parâmetro – computername, como em:
Get-OSInfo –computername Server-R2,ServerDC4 | Format-Table
  • Aceitar do pipeline de um ou mais objetos que cada um tem uma propriedade de nome do computador, como em:
Get-ADComputer –filter * -searchbase "ou=West,dc=company,dc=com" | Select-Object @{label='computername';expression={_.Name}} | Get-OSInfo | Export-CSV inventory.csv

Desta forma, você não precisará se preocupar sobre onde nomes de computador são provenientes. Também nunca precisa se preocupar com o tipo de saída você vai criar. O shell vai lidar com isso.

Além disso, você vai querer ter um parâmetro de –logfile, que aceitará um caminho e nome de arquivo de um arquivo de log. Porque o comando ainda estarão usando Windows Management Instrumentation (WMI) para se conectar e consultar informações, é possível que você não será capaz de chegar a um ou mais computadores. Você ainda precisa ter seus nomes gravados para o arquivo de log, que você pode usar para solucionar o problema ou até mesmo para repetir esses computadores.

Lidar com erros

Você pode realizar esse último bit usando o tentar...Construção de Catch dentro do PowerShell. Simplesmente encapsular a primeira consulta WMI em um tentar...Catch Bloquear. Em seguida, especifique o parâmetro Stop –ErrorAction assim será capaz de detectar quaisquer erros que o comando gera. Defina uma variável que controla se um erro ocorreu, assim que seu script saberá se deve tentar as duas próximas consultas WMI:

continue = True
Try {
  Get-WmiObject –class Win32_BIOS –computername computername –EA Stop
} Catch {
  continue = False
  computername | Out-File –path logfile –append
}

Lidar com o contributo

A parte difícil é lidar com a entrada. Você vai receber entrada em uma destas duas maneiras — via pipeline ou por meio de um parâmetro. Você realmente pode direcionar entrada vindo via pipeline para o parâmetro, usando ligação de parâmetro de cmdlet-estilo. Aqui é a estrutura básica de que:

Function Get-OSInfo {
  [CmdletBinding()]
  param(
    [Parameter(Mandatory=True,ValueFromPipeline=True,ValueFromPipelineByPropertyName=True)]
  [string[]]computername,
  [string]logfile 
 )
  BEGIN {}
  PROCESS {}
  END {}
}

O bloco de processo dentro do cmdlet é garantido para executar pelo menos uma vez, que ele vai fazer se não houver nenhuma entrada de pipeline fornecida. Se não houver entrada de pipeline fornecida, o bloco de processo será executado uma vez para cada item de canalizado. Ele vai colocar esse item na variável computername.

É aí que reside o problema: Se a entrada só é especificada por meio de um parâmetro, como no segundo exemplo com marcadores, em seguida, processo só será executado uma vez. O computername irá conter cada nome de computador que foi dado para o parâmetro. Você teria que enumerar ou "desanuviar" essas mesmo. Se esses itens são canalizados, só vou ter trabalho com um item por vez. Você ainda vai recebê-los na variável computername.

O truque é criar uma segunda função que faz o trabalho real. Use a função avançada para aceitar qualquer tipo de entrada e dividir as coisas em nome de um computador por vez. Então chame a função de "trabalhador" segunda com um nome único computador por vez. Aqui é a estrutura básica, que iria dentro do bloco de processo da função principal:

PROCESS {
  if (PSBoundParameters.ContainsKey('computername')) {
    foreach(computer in computername) {
      OSInfoWorker –computername computer –logfile logfile
    }
  } else {
    OSInfoWorker –computername computername –logfile logfile
  }
}

Finalizando

Com os principais obstáculos técnicos resolvidos, trazê-lo todos juntos e adicionar alguns outros detalhes, como a limpeza de arquivos de log antigos antes de executar a função de cada vez (que é um candidato perfeito para o bloco BEGIN). O script resultante, constituído por duas funções, é um pouco demorado. No entanto, muito pouco do é real "programação". A maior parte é apenas comandos do Windows PowerShell, como você seria executado na linha de comando. Eles apenas estão rodeados de muita estrutura declarativa para fazer com que todos se comportam como um cmdlet.

A coisa toda é postada em meu Web site at de ow.ly/39YcX , juntamente com um vídeo passo a passo do código final. Este é um modelo que é absolutamente possível reutilizar. A principal função é realmente apenas lidar com a entrada, assim você pode usá-lo quase como é. Alterar os parâmetros de acordo com suas necessidades específicas, e você está pronto para ir. O trabalho real está sendo feito em uma função separada.

No próximo mês, mostrarei como empacotar Tudo isso como um módulo de script fácil de distribuir. Também mostrarei como configurar um local compartilhado para os módulos de script que todos os seus colegas de administrador podem utilizar.

Don Jones

Don Jones é dos fundadores da tecnologia concentrado e respostas a perguntas sobre o Windows PowerShell e outras tecnologias em ConcentratedTech.com. Ele também é um autor de Nexus.Realtimepublishers.com, que disponibiliza muitos de seus livros como free edições electrónicas através de seu web site.

 

Obtenha mais

Artigo deste mês tem um companheiro vídeo demonstra passo a passo, bem como código de exemplo para download. Obter esses extras aqui.

Conteúdo relacionado