Windows PowershellA eficiência das variáveis

Don Jones

Se você trabalha com uma linguagem de script com base em Windows, como o VBScript ou o KiXtart, já está acostumado em tratar variáveis como nada mais do que um tipo de mecanismo de armazenamento para dados. O Windows PowerShell também tem variáveis, mas elas são muito mais eficientes do que as variáveis em linguagens de scripts mais antigas. Na verdade, as variáveis do Windows

PowerShell são mapeadas para classes subjacentes no Microsoft® .NET Framework. E, no Framework, variáveis são objetos, o que envolve a sua capacidade de armazenar dados e também de manipular esses dados de várias maneiras. De fato, os sólidos recursos de variáveis no Windows PowerShell™ são o motivo pelo qual a linguagem de script do Windows PowerShell não contém funções intrínsecas de manipulação de dados. Essas funções não são necessárias, uma vez que as próprias variáveis já oferecem a funcionalidade.

Declarando variáveis

Embora o cmdlet New-Variable no Windows PowerShell permita a declaração de uma variável e a atribuição de um valor inicial a ela, não é necessário usar cmdlet. Em vez disso, você pode criar uma nova variável de forma dinâmica, simplesmente atribuindo um valor a ela:

$var = "Hello"

No Windows PowerShell, os nomes de variáveis sempre começam com um sinal de cifrão ($) e podem conter uma combinação de letras, números, símbolos ou até mesmo espaços (apenas de que, se você usar espaços, será necessário delimitar a variável entre chaves, como ${Minha variável} = "Olá"). Esse exemplo criou uma nova variável denominada $var e atribuiu a ela o valor inicial "Olá". Como, nesse caso, o valor é uma seqüência de caracteres, o Windows PowerShell usará o tipo de dados Seqüência de caracteres para armazenar o valor. No que diz respeito ao .NET Framework, essa é a classe System.String, que talvez tenha a funcionalidade mais integrada de qualquer tipo de variável. Digamos que, se quiser ver uma versão totalmente em minúsculas do valor em $var, eu possa fazer o seguinte:

PS C:\> $var.ToLower()
hello
PS C:\>

O método ToLower é integrado à classe System.String e gera uma representação totalmente em minúsculas do valor da seqüência de caracteres. Porém, ele não altera o conteúdo real da variável $var. Para ver uma lista completa de tudo o que a classe System.String é capaz de fazer, conduza uma variável de seqüência de caracteres para o cmdlet Get-Member, como a seguir:

$var | get-member

A Figura 1 mostra a saída, que inclui algumas dezenas de métodos usados para a manipulação de seqüências de caracteres. Quase toda a funcionalidade fornecida pelas funções de manipulação de seqüências de caracteres de VBScript é determinada em vez disso por métodos da variável de seqüência de caracteres no Windows PowerShell.

Figure 1 A look at the System.String class output

Figure 1** A look at the System.String class output **(Clique na imagem para aumentar a exibição)

Muitos dos recursos da variável de seqüência de caracteres são mais úteis em um contexto administrativo do que as funções de seqüência de caracteres em uma linguagem como VBScript. Suponha que você tenha gravado um script que realize leituras em caminhos UNC (Universal Naming Convention) a partir de um arquivo e que faça algo com esses caminhos. Você deseja verificar se cada caminho lido está em um UNC antes de tentar usar um determinado caminho. O método StartsWith permite confirmar se o valor de uma string começa com os caracteres de barra invertida necessários para um UNC:

PS C:\> $path = "\\Server\Share"
PS C:\> $path.StartsWith("\\")
True
PS C:\>

Como StartsWith retorna um valor True ou False, é possível usá-lo em construções lógicas:

if ($path.StartsWith("\\")) {
 # code goes here
}

O Windows PowerShell fornece até mesmo uma forma de auto-preenchimento para métodos de variáveis, reduzindo a quantidade de digitação necessária. Se $var contiver uma string, você poderá digitar

$var. 

e depois pressionar Tab, o que ativa o primeiro nome de método da variável $var. Pressionar Tab novamente faz com que o método seguinte seja acessado, enquanto pressionar Shift+Tab ativa o método anterior. Dessa forma, você pode percorrer todos os métodos de variáveis até encontrar o desejado.

Confusão de variáveis

Até agora, meus exemplos permitiram que o Windows PowerShell determinasse o tipo de dados das minhas variáveis. A atribuição de uma seqüência de caracteres a uma variável força essencialmente essa variável para que ela seja da classe System.String. Por outro lado, a atribuição de um número a uma variável geralmente faz com que a variável se torne um Inteiro (ou, mais especificamente, um Int32, que pode armazenar um intervalo específico de valores). Por exemplo, considere o seguinte:

PS C:\> $int = 5
PS C:\> $int | get-member

  TypeName: System.Int32

Essa saída truncada mostra que o Windows PowerShell está tratando $int como Int32, que possui o seu próprio conjunto de métodos e propriedades. E, de fato, seu conjunto de métodos e propriedades é muito menor do que o do tipo Seqüência de caracteres.

$int se tornou Int32 porque o valor não estava delimitado por aspas e porque era composto unicamente por dígitos. Se estivesse entre aspas, teria sido interpretado como System.String.

Permitir que o Windows PowerShell decida que tipo de dados deve ser usado nem sempre gera os resultados desejados. Suponha que você esteja lendo valores a partir de um arquivo e sempre queira que esses valores sejam tratados como seqüências de caracteres. Entretanto, alguns dos valores podem conter apenas dígitos, levantando a possibilidade de o Windows PowerShell tratá-los como Int32 ou outro valor numérico. Isso pode causar problemas para o script. Se o Windows PowerShell não reconhecer o valor como seqüência de caracteres, nenhum dos métodos da classe System.String estará disponível (e o seu script pode depender de um desses métodos não disponíveis).

Para solucionar o problema, você pode forçar o Windows PowerShell a tratar uma variável como um certo tipo, declarando esse tipo ao usar essa variável pela primeira vez. Por exemplo:

[string]$var = 5

Normalmente, $var teria sido Int32, mas, neste caso, forcei o Windows PowerShell a tornar $var uma Seqüência de caracteres, garantindo a possibilidade de usar todos os métodos associados à classe System.String. A declaração de tipo de variável também fornece um tipo prático de auto-documentação para o código, já que agora está óbvio qual é o tipo de dados que se espera inserir em $var. De fato, adotei o hábito de sempre declarar um tipo específico para todas as minhas variáveis, afastando a decisão totalmente do Windows PowerShell. Isso torna o comportamento dos meus scripts mais previsível e, em vários casos, poupou um considerável tempo de depuração.

Como é de se esperar, a declaração forçada de variáveis tem as suas repercussões, embora não sejam necessariamente más. Considere esse exemplo, que não declara o tipo da variável:

PS C:\> $me = 5
PS C:\> $me = "Don"

A variável $me era inicialmente Int32, mas o Windows PowerShell a alterou para uma Seqüência de caracteres quando o valor "Don" foi adicionado. O Windows PowerShell pode alterar o tipo de uma variável conforme necessário, desde que a variável ainda não tenha sido explicitamente definida como um tipo específico.

Nesse exemplo, forcei $me para ser um Int32 usando o nome do tipo [int]:

PS C:\> [int]$me = 5
PS C:\> $me = "Don"
Cannot convert value "Don" to type 
"System.Int32". Error: "Input string 
was not in a correct format."
At line:1 char:4
+ $me <<<< = "Don"

Depois, quando tentei atribuir um valor de seqüência de caracteres a ele, uma mensagem de erro foi exibida. Como forcei explicitamente $me para que ele fosse Int32, o Windows PowerShell esperava converter a seqüência de caracteres "Don" em um valor inteiro. Ele não pode fazer isso ou não conseguiu alterar o tipo de $me para Seqüência de caracteres.

Tantos tipos

Existem muitos tipos disponíveis no Windows PowerShell. De fato, é possível usar qualquer tipo do .NET Framework (e o número de tipos disponíveis às centenas). Entretanto, o Windows PowerShell define vários atalhos para tipos comuns de dados. A Figura 2 é apenas uma lista parcial, mostrando 10 dos atalhos de tipos mais comumente utilizados. Para obter uma lista completa, consulte a documentação do Windows PowerShell.

Figure 2 Atalhos de tipos comuns

Atalho Tipo de dados
[datetime] Data ou hora
[string] Seqüência de caracteres
[char] Caractere simples
[double] Número flutuante de precisão dupla
[single] Número flutuante de precisão única
[int] Inteiro de 32 bits
[wmi] Instância ou coleção do WMI
[adsi] Objeto de serviços do Active Directory
[wmiclass] Classe do WMI
[Boolean] Valor True ou False

Você também pode declarar o tipo de uma variável usando o nome completo da classe do .NET Framework, por exemplo:

[System.Int32]$int = 5

Essa técnica permite usar tipos que estão no .NET Framework, mas que não têm um atalho específico no Windows PowerShell.

Estendendo tipos

Talvez o mais interessante sobre o Windows PowerShell seja a sua capacidade de estender os recursos desses tipos de variáveis. Na pasta de instalação do Windows PowerShell (normalmente em %systemroot\system32\windowspowershell\v1.0, embora você venha a perceber que o caminho é um pouco diferente em sistemas de 64 bits), haverá um arquivo denominado types.ps1xml. É possível editar esse arquivo no Bloco de Notas ou em um editor XML, como o PrimalScript. Por padrão, a classe System.String não está listada, embora muitos outros tipos estejam. Entretanto, posso adicionar um novo recurso ao tipo System.String adicionando isso ao arquivo types.ps1xml.

Depois de fazer a alteração, preciso fechar e reabrir o Windows PowerShell. Também preciso ter certeza de que a diretiva de execução de scripts locais permita a execução de scripts não assinados, já que eu não assinei types.ps1xml:

Set-executionpolicy remotesigned

Agora, depois de reiniciar Windows PowerShell, posso usar a nova funcionalidade, dessa maneira:

PS C:\> [string]$comp = "localhost"
PS C:\> $comp.canping
True
PS C:\>

Como é possível perceber, adicionei uma propriedade CanPing à classe System.String. Isso retorna True ou False para indicar se o computador local é capaz de executar ping do endereço contido na seqüência de caracteres. Na Figura 3, você perceberá que a consulta do WMI utiliza uma variável especial, $this. A variável $this representa o valor atual contido na seqüência de caracteres e representa a forma como o conteúdo da seqüência de caracteres é transmitido em uma consulta do WMI.

Figure 3 Estender o tipo System.String

<Type>
  <Name>System.String</Name>
  <Members>
    <ScriptProperty>
      <Name>CanPing</Name>
      <GetScriptBlock>
      $wmi = get-wmiobject -query "SELECT *
FROM Win32_PingStatus WHERE Address = '$this'"
      if ($wmi.StatusCode -eq 0) {
        $true
      } else {
        $false
      }
      </GetScriptBlock>
    </ScriptProperty>
  </Members>
</Type>

Deixe que uma variável faça o trabalho

O Windows PowerShell fornece tipos de variáveis flexíveis e cheios de recursos, além de um sistema igualmente flexível para estender a funcionalidade de tipos. Esses recursos tornam muito fácil a integração de muita eficiência aos seus scripts. De fato, as variáveis podem se tornar um elemento principal em scripts complexos, em muitos casos utilizando os recursos avançados normalmente encontrados em uma função mais complexa.

Aprenda mais online

Participe dessa série de Webcasts que ocorrerá na segunda terça-feira de cada mês, quando continuaremos a discutir a elaborada funcionalidade de scripts fornecida pelo Windows PowerShell. Visite o endereço microsoft.com/events/series/donjonesscripting.mspx para inscrever-se hoje mesmo.

20 de fevereiro de 2007 - Windows PowerShell: O curso rápido de scripts

Participe deste Webcast para aprender sobre variáveis, construções de linguagens, scripts e funções no Windows PowerShell. Nesse curso rápido de uma hora, demonstraremos como a linguagem de script simples, mas eficaz, no Windows PowerShell torna mais rápida a automação administrativa do Windows®. Também exploraremos várias ferramentas de terceiros que tornam os scripts do Windows PowerShell os mais simples possíveis.

20 de março de 2007 - Windows PowerShell: funções, filtros e eficácia

Aprenda a criar um código eficaz e modularizado nas funções e nos filtros do Windows PowerShell. Exploraremos as sólidas regras de criação de escopo no Windows PowerShell que permitem escapsular totalmente funções e filtros e que explicam como é possível reutilizar facilmente essas funções e esses filtros em projetos. Também demonstraremos como é possível adicionar as suas próprias funções personalizadas ao escopo global do Windows PowerShell, o que facilita a montagem nas pontas dos dedos de uma biblioteca de úteis funções de utilitários.

17 de abril de 2007 - Windows PowerShell e Windows Management Instrumentation

O Windows PowerShell pode acessar toda a eficiência e todos os recursos do WMI (Windows Management Instrumentation). Descreveremos não só como usar o Windows PowerShell para acessar o WMI, mas também como transmitir objetos e coleções do WMI por meio do pipeline do Windows PowerShell. Exploraremos como utilizar as propriedades e os métodos do WMI nos scripts do Windows PowerShell e ilustraremos os recursos de segurança e de configuração subjacentes no WMI.

22 de maio de 2007 - Windows PowerShell: convertendo a partir do VBScript

Deseja converter scripts, ou até mesmo as suas habilidades, do VBScript para o Windows PowerShell? Participe deste Webcast para aprender como. Exploraremos como o Windows PowerShell inclui todas as principais construções e recursos do VBScript, facilitando a conversão de habilidades do VBScript para esse novo ambiente administrativo. Ilustraremos como converter ferramentas no VBScript para a linguagem de script nativa no Windows PowerShell. Também examinaremos a estrutura exclusiva no Windows PowerShell e mostraremos como começar a usar a linguagem de script do Windows PowerShell para que os seus esforços se tornem ainda mais eficientes e eficazes.

19 de junho de 2007 - Windows PowerShell: Extensões subjacentes

Nesse Webcast, exploraremos como o Windows PowerShell utiliza o eficiente e flexível .NET Framework para controlar dados, fornecendo centenas de funções integradas para gerenciar seqüências de caracteres, datas e outros tipos de dados. Mas, você sabia que é possível estender essas funções usando scripts do Windows PowerShell? Mostraremos como criar variáveis de seqüências de caracteres que contêm não apenas um nome de computador, mas que também informam se esse computador está ativo e em execução. Aprenda a criar variáveis de data e hora que podem formatar seus dados automaticamente sem o uso de funções externas. Participe dessa sessão para aprender a criar todos os tipos de novas funcionalidades no Windows PowerShell em questão de minutos, tornando a administração do Windows mais rápida e mais fácil.

Don Jones é diretor de projetos e serviços da SAPIEN Technologies e co-autor do Windows PowerShell: TFM (SAPIEN Press). Entre em contato com Don no endereço www.ScriptingAnswers.com.

© 2008 Microsoft Corporation e CMP Media, LLC. Todos os direitos reservados. A reprodução parcial ou completa sem autorização é proibida..