NET Server Resource Kit. Quando combinado a ... Visual Basic® Scripting
Edition (VBScript) torna-se uma linguagem de scripts poderosa. Usando o
VBScript ...
Manual do VBScript Este artigo é derivado do System Administration Scripting Guide, um novo livro que será publicado como parte do Windows .NET Server Resource Kit. Quando combinado a tecnologias como a instrumentação de gerenciamento do Windows (WMI) e as interfaces de serviço do Active Directory (ADSI), o Microsoft® Visual Basic® Scripting Edition (VBScript) torna-se uma linguagem de scripts poderosa. Usando o VBScript juntamente com essas tecnologias, você pode escrever um script de aproximadamente 10.000 linhas, um script completo com tratamento de erros, sub-rotinas e outras construções de programação avançadas. Por sua vez, esse script fornece a você controle completo sobre todos os aspectos do seu ambiente de computação. No entanto, o que torna o VBScript uma ferramenta tão útil para administradores de sistema é o fato de que não é preciso criar soluções tão elaboradas e complicadas. Reconhecidamente, scripts podem ser usados para criar uma solução de gerenciamento empresarial abrangente. Porém, talvez o mais importante seja o fato de que os scripts também podem ser usados do seguinte modo: um administrador do sistema pode gastar alguns minutos digitando algumas linhas de código no Bloco de Notas e criar instantaneamente uma solução personalizada para um problema específico. Por exemplo, o script de três linhas mostrado na listagem 1 pode ser executado sempre que você precisar saber a quantidade de espaço livre em disco disponível na unidade C do seu computador. Listagem 1 Recuperando espaço livre em disco com o VBScript 1 Set objWmiService = GetObject("winmgmts:") 2 Set objLogicalDisk = objWmiService.Get("Win32_LogicalDisk.DeviceID='C:'") 3 WScript.Echo objLogicalDisk.FreeSpace Se estiver enfrentado problemas com usuários que utilizam muito espaço na unidade C de seus computadores, agora você tem uma solução personalizada para identificar os computadores com pouco espaço livre em disco. Além disso, você pode desenvolver
essa solução personalizada usando somente o Bloco de Notas e só precisará digitar as três linhas de código já mencionadas. É claro que talvez esse script não atenda completamente às suas necessidades. Por exemplo, o script só informa a respeito do espaço livre em disco disponível no seu computador local; ele não pode informar a quantidade de espaço livre disponível em um computador remoto. Da mesma forma, o script relata apenas o espaço livre disponível na unidade C; ele não informa nada a respeito do espaço livre disponível nas unidades D e E, por exemplo. Porém, se o script não atender completamente às suas necessidades, ele poderá ser facilmente modificado, sem que seja preciso iniciar um novo script a partir do zero. Essa é outra vantagem do VBScript: é possível iniciar com um script muito simples e adicionar recursos a ele à medida que suas necessidades forem mudando e você for se tornando mais proficiente com a linguagem. Conceitos básicos do VBScript Este artigo foi criado para ilustrar o processo de se começar com um script básico e de se adicionar, gradualmente, mais recursos sofisticados a ele. O artigo começa com o script mostrado na listagem 1, um script que relata o espaço livre em disco na unidade C. Seções subseqüentes usarão esse script simples de três linhas e gradualmente adicionarão mais recursos para torná-lo mais útil em mais situações. Quando essa série de aprimoramentos estiver completa, você terá um script que pode: •
Recuperar informações sobre o espaço livre em disco de qualquer computador de sua empresa, inclusive computadores remotos.
•
Recuperar informações sobre o espaço livre em disco de vários computadores.
•
Recuperar informações sobre o espaço livre em disco de todas as unidades instaladas em um computador.
•
Emitir uma notificação somente se uma unidade tiver pouco espaço em disco.
•
Continuar funcionando caso um usuário digite um nome de computador inválido ou caso um computador não esteja disponível na rede.
À medida que os novos recursos forem adicionados ao script, as construções do VBScript necessárias para fornecer esses aprimoramentos também serão brevemente
explicadas. (No capítulo do System Administration Scripting Guide do qual esse arquivo é derivado, essas construções são explicadas em mais detalhes.) Trabalhando com objetos O VBScript permite a administradores do sistema criar scripts complexos usando recursos de programação avançados, como árvores de decisão, loop, tratamento de erros e a capacidade de chamar funções e sub-rotinas. Porém, o VBScript não inclui funções intrínsecas à execução de tarefas de administração de sistemas. O VBScript possui funções internas para a determinação da raiz quadrada de um número ou do valor ASCII de um caractere, mas não possui funções internas para a interrupção de serviços, para a recuperação de eventos em logs de eventos ou para a execução de outras tarefas do interesse de administradores de sistemas. Usando objetos COM Felizmente, há maneiras de se executar essas tarefas por meio de programação. Isso é feito basicamente através do uso de objetos de automação. Objetos de automação são um subconjunto de COM (modelo de objeto componente), uma forma padrão de aplicativos (arquivos .exe) ou bibliotecas de programação (arquivos .dll) apresentarem seus recursos como uma série de objetos. Por sua vez, os programadores (ou escritores de script) podem utilizar esses objetos -- e os recursos do aplicativo ou da biblioteca de programação -- em seus próprios projetos. Por exemplo, um aplicativo de processamento de texto pode expor o verificador ortográfico como um objeto de automação, fornecendo aos escritores de script uma maneira de adicionar a verificação ortográfica a seus projetos. A capacidade de trabalhar com objetos de automação e utilizar as propriedades e os métodos desses objetos torna o VBScript uma ferramenta poderosa para administração de sistemas. O VBScript sozinho não pode ler eventos em um log; no entanto, ele pode usar os recursos incluídos na WMI para recuperar esses eventos. O VBScript não possui funções intrínsecas à criação de contas de usuário no Active Directory; porém, a linguagem pode usar os recursos da ADSI para criar essas contas. Na verdade, o VBScript é freqüentemente chamado de "linguagem cola", pois uma de suas aplicações principais é "colar" objetos. Em vez de fornecer um número infinito de funções intrínsecas dedicadas à administração de sistemas, o VBScript fornece duas funções,
GetObject e CreateObject, e os elementos de linguagem necessários para o uso dos métodos e das propriedades de objetos de automação. O script mostrado na listagem 2 ilustra a importância de objetos de automação no VBScript. Esse script relata a quantidade de espaço livre em disco na unidade C do computador local. E, ainda, ele faz isso usando pouco código VBScript. Em vez disso, o script: 1. Usa a função VBScript GetObject para se conectar à WMI através da biblioteca de scripts WMI (um objeto de automação). 2. Usa o método Get, fornecido pelo objeto de automação WMI, para recuperar as propriedades da unidade C. 3. Usa o método Echo do Windows Script Host (WSH) para relatar a quantidade de espaço livre em disco na unidade C. Aliás, WSH é apenas outro objeto de automação. Listagem 2 Usando objetos no VBScript 1 Set objWmiService = GetObject("winmgmts:") 2 Set objLogicalDisk = objWmiService.Get("Win32_LogicalDisk.DeviceID='C:'") 3 WScript.Echo objLogicalDisk.FreeSpace No exemplo anterior, o objetivo principal do VBScript era colar os recursos da WMI e do WSH. Isso permitiu a você recuperar o espaço livre em disco (algo que o WSH não pode fazer sozinho) e exibir o valor de volta para a tela (algo que a WMI não pode fazer sozinha). Criando objetos Antes de utilizar os métodos ou as propriedades de um objeto de automação, você deve obter uma referência ao objeto, um processo conhecido como criar ou determinar o objeto. Criar objetos pode parecer confuso à primeira vista, pois o VBScript e o WSH fornecem os métodos CreateObject e GetObject para acessar objetos. Além disso, embora as implementações sejam semelhantes, há algumas diferenças sutis que crescem em importância à medida que você se torna proficiente em scripts. Essas diferenças são discutidas em mais detalhes no livro. Por enquanto, use as seguintes diretrizes práticas sem se preocupar com o fato de estar usando as funções do VBScript ou os métodos do WSH (porém, na maioria dos casos, você usará as funções do VBScript):
•
Use GetObject para criar objetos WMI ou ADSI. Quando estiver utilizando GetObject, use um identificador de origem para identificar o objeto a ser criado. Um identificador de origem é simplesmente uma seqüência de caracteres, com um prefixo obrigatório, que facilita a descrição do objeto de destino, da mesma forma como um nome de arquivo e um caminho completo descrevem um arquivo específico no sistema de arquivos.
•
Use CreateObject para criar objetos que não sejam WMI ou ADSI. CreateObject usa um identificador por meio de programação, ProgID, para identificar o objeto a ser criado. Um ProgID é a seqüência de caracteres fixa que um objeto adiciona ao Registro quando o objeto é instalado e registrado no computador. Prefixos de identificador de origem também são armazenados no Registro.
Estas não são regras fixas; algumas vezes você precisará usar CreateObject para criar objetos WMI que não sejam SWbemServices (por exemplo, SWbemDateTime). Alguns objetos ADSI exigem, de forma semelhante, o uso de CreateObject. Porém, em geral, CreateObject será necessário somente durante a criação de novas instâncias de itens como objetos de shell, de rede e de controlador do WSH, objetos de dicionário, FileSystemObject e o Internet Explorer, entre vários outros objetos. Objetos intrínsecos Alguns objetos são intrínsecos. Objetos intrínsecos são os objetos criados sem nunca ter sido necessário efetuar uma chamada para GetObject ou CreateObject. No script mostrado na listagem 2, o script conecta-se à WMI usando este código: Set objWmiService = GetObject("winmgmts:") Isso cria uma referência, chamada objWmiService, ao objeto SwbemServices da biblioteca de scripts WMI. Observe que nenhuma seqüência de caracteres semelhante é usada para criar uma referência ao objeto Wscript do WSH na listagem 2. Em vez disso, o método Echo é chamado sem a criação anterior de qualquer tipo de objeto WSH. Isso ocorre porque WScript é um objeto intrínseco. Não é necessário criar um objeto Wscript, pois WScript será criado automaticamente quando você executar um script de VBScript. O objeto de erro do VBScript, Err, é outro objeto intrínseco. O objeto Err será criado automaticamente quando ocorrer um erro no script. Examinaremos o objeto Err posteriormente neste artigo. Usando uma referência de objeto
Com a automação, você não trabalha diretamente com o próprio objeto. Em vez disso, você cria uma referência ao objeto usando GetObject ou CreateObject e atribuindo o objeto a uma variável. Após a criação dessa referência, você poderá acessar os métodos e as propriedades do objeto usando a variável e não o objeto propriamente dito. Na listagem 2, GetObject é usado para atribuir o objeto SWbemServices da WMI à variável objWmiService. Depois que a atribuição for concluída, todos os métodos e as propriedades do objeto SWbemServices poderão ser acessados através de objWmiService. Por exemplo, na linha 2 do script, o método Get é usado para recuperar as propriedades da unidade C. Sempre que criar uma referência de objeto, você deverá usar a palavra-chave Set quando atribuir a referência a uma variável. Por exemplo, esta linha de código resultará em erro em tempo de execução: objWmiService = GetObject("winmgmts:") Para criar a referência do objeto, use a palavra-chave Set da seguinte maneira: Set objWmiService = GetObject("winmgmts:") Set só é usada durante a criação de uma referência de objeto. Se você usar essa palavra-chave para outros propósitos, como atribuir um valor a uma variável, ocorrerá um erro em tempo de execução. Por exemplo, esta linha de código falhará, pois nenhum objeto chamado y poderá ser encontrado no computador: Set x = y Métodos de chamada Os objetos de automação permitem usar os recursos dos objetos nos scripts. Por sua vez, isso permite a você criar scripts mais úteis e poderosos do que faria se estivesse restrito aos recursos da linguagem de scripts. Por exemplo, é impossível desenhar um gráfico usando somente o VBScript. No entanto, com a automação, você pode utilizar os recursos do Microsoft Excel e adicionar facilmente um gráfico a, por exemplo, uma página da Web. Normalmente, os objetos de automação expõem métodos e propriedades (porém, não há requisitos para que exponham nenhum dos dois). Os métodos são equivalentes às ações que os objetos podem executar. Por exemplo, embora o script da listagem 2 tenha somente três linhas, ele usa a automação para acessar os métodos de dois objetos COM diferentes e, assim, executar duas ações distintas:
•
O método Get, disponível através do objeto SWbemServices da WMI. O método Get recupera informações do recurso gerenciado pela WMI especificado.
•
O método Echo, disponível através do objeto WScript. O método Echo exibe informações na tela. Se um script estiver sendo executado em uma janela de prompt de comando e, portanto, sob Cscript.exe, essa informação será exibida dentro dessa janela. Se o script estiver sendo executado sob Wscript.exe, a informação será exibida em uma caixa de diálogo.
Depois de criar uma referência a um objeto, você poderá chamar os métodos desse objeto usando a notação de pontos. A notação de pontos tem esse nome, pois você chama um método digitando o nome da variável que faz referência ao objeto, um ponto e o nome do método (dependendo do método, você também poderá digitar seus parâmetros). Geralmente, a notação de pontos tem a seguinte aparência: Referência_de_Objeto.Nome_do_Método Na listagem 2, a chamada do método Get de SWbemServices pode ser dividida conforme mostrado na tabela 1. Tabela 1 Item
Descrição
objWmiService
Referência do objeto.
.
Ponto (separa a referência do objeto e o nome do método).
Get
Nome do método.
("Win32_LogicalDisk.DeviceID='C:'") Parâmetro do método. Para o método Get, isso pode ser lido como "Obtenha a instância da classe Win32_LogicalDisk onde DeviceID é igual a C:". Uma observação sobre Wscript.Echo Em vez de usar Wscript.Echo para exibir o espaço livre em disco, você pode usar a função Msgbox do VBScript: Msgbox objLogicalDisk.FreeSpace Porém, neste artigo, usaremos Wscript.Echo e não Msgbox. Isso será feito porque a função Msgbox sempre exibe as informações em uma caixa de diálogo gráfica. Quando essa caixa de diálogo for exibida, você deverá clicar no botão OK antes que o script prossiga.
Recuperando propriedades Propriedades são atributos associados a um objeto. Elas são especialmente importantes em scripts de administração de sistemas, pois vários dos objetos que você usa são representações virtuais de objetos reais de sistema operacional e de computador. Na listagem 2, a propriedade FreeSpace é recuperada com a mesma notação de pontos usada para chamar métodos. Isso pode parecer irrelevante, mas com a WMI, a referência não é algum algoritmo de programação amorfo, mas sim a um disco rígido real no computador. Portanto, a propriedade FreeSpace não é somente uma propriedade de um objeto de automação; ela é uma propriedade da unidade C. De certa maneira, WMI cria um espelho virtual de um objeto físico real. Quando você recupera as propriedades desse espelho virtual, também recupera as propriedades do objeto físico. Variáveis O script mostrado na listagem 2 funciona exatamente como o esperado; quando executado, ele relata o espaço livre em disco na unidade C. Porém, isso não significa que o script não possa ser aprimorado. Por exemplo, a propriedade FreeSpace informa o número de bytes disponíveis em uma unidade. Como unidades de disco são normalmente medidas em gigabytes, quase sempre a propriedade FreeSpace retorna um valor difícil de interpretar. Por exemplo, a figura 1 mostra o valor relatado para uma unidade com aproximadamente 10 gigabytes de espaço livre em disco.
Figura 1 Embora pareça óbvio que a unidade C possui espaço em disco adequado, é muito menos óbvio a quantidade de espaço em disco realmente disponível. Administradores de sistema podem achar fácil interpretar os dados retornados pelo script, caso os dados sejam relatados como megabytes em vez de bytes. O VBScript inclui uma grande variedade de funções matemáticas que permitem executar ações, como a conversão de bytes em megabytes. Além disso, o VBScript também fornece uma construção -- a variável -- que pode ser usada para armazenar os resultados dessas equações matemáticas. Variáveis fornecem uma maneira de armazenar qualquer tipo de dado enquanto o script está sendo executado.
Variáveis representam partes da memória disponíveis ao script durante sua execução. Com essa finalidade, você pode pensar em memória de computador como sendo uma série de pequenos compartimentos. Uma variável nada mais é do que um desses compartimentos com um rótulo identificador anexado. Você pode armazenar qualquer tipo de dado nesse compartimento e ter certeza de que o VBScript poderá recuperar os dados se necessário. Quando você desejar fazer referência a esses dados, o VBScript simplesmente procurará o endereço da memória e relatará as informações lá armazenadas. Usando variáveis Como outras linguagens de script comuns, as variáveis do VBScript podem ser criadas e usadas imediatamente em qualquer ponto de um script. Você não precisa se preocupar em declarar ou inicializar uma variável antes de usá-la. (Por outro lado, há algumas vantagens em declarar e inicializar variáveis antes de usá-las. Para obter detalhes, consulte o System Administration Scripting Guide.) Na linha 3 da listagem 3, uma variável chamada FreeMegabytes é usada para armazenar os resultados da divisão de FreeSpace por 1048576 (o valor necessário para converter bytes em megabytes). Assim que a linha 3 for executada, a variável FreeMegabytes assumirá o valor dessa equação. Se for necessário fazer referência ao número de megabytes de espaço livre em disco em qualquer outro local do script, você não precisará repetir essa equação. Em vez disso, simplesmente faça referência à variável FreeMegabytes. Isso é mostrado na linha 4, onde o valor da variável é exibido para a tela. Listagem 3 Usando variáveis 1 Set objWmiService = GetObject("winmgmts:") 2 Set objLogicalDisk = objWmiService.Get("Win32_LogicalDisk.DeviceID='C:'") 3 FreeMegaBytes = objLogicalDisk.FreeSpace / 1048576 4 WScript.Echo FreeMegaBytes A Figura 2 mostra o valor relatado como megabytes.
Figura 2 Observação A equação usou o número 1048576 e não o número 1.048.576 (com pontos para separar os milhares). Você não pode usar pontos ou qualquer outro caractere para separar milhares no VBScript. Em vez disso, você deve executar todos os dígitos juntos. Isso se aplica a números embutidos em código no script, bem como
números inseridos como um argumento de linha de comando ou como resposta a qualquer tipo de solicitação. Modificando variáveis Provavelmente, o valor 10340.4458007813 (significando 10.340 megabytes de espaço livre) é muito mais significativo para o administrador de sistema típico do que o valor 10842824704. Porém, pode-se argumentar que os números após o ponto decimal não contêm muitas informações úteis. Felizmente, o VBScript fornece várias maneiras diferentes para você modificar os dados armazenados em variáveis. Por exemplo, a função Int retorna a parte inteira de um número, deixando de fora todos os dígitos após o ponto decimal. Portanto, você pode usar a função Int para modificar o valor decimal armazenado no compartimento FreeMegaBytes, conforme mostrado na linha 4 da listagem 4. Listagem 4 Modificando variáveis 1 Set objWmiService = GetObject("winmgmts:") 2 Set objLogicalDisk = objWmiService.Get("Win32_LogicalDisk.DeviceID='C:'") 3 FreeMegaBytes = objLogicalDisk.FreeSpace / 1048576 4 FreeMegaBytes = Int(FreeMegaBytes) 5 WScript.Echo FreeMegaBytes A função Int recupera o valor decimal original, descarta todos os dígitos após o ponto decimal e retorna somente a parte inteira arredondada do número, que sobrescreve o valor original armazenado no compartimento FreeMegaBytes (variável). Quando o script da listagem 4 for executado, FreeMegaBytes será relatado como um número inteiro, conforme mostrado na figura 3.
Figura 3 Constantes No script mostrado na listagem 3, a quantidade de megabytes livres é calculada através da divisão do valor da propriedade FreeSpace pelo valor embutido em código 1048576 (valores embutidos em código como esse são chamados de literais, pois representam literalmente o valor e não variáveis). Em um script pequeno como esse (especialmente, um script pequeno escrito para seu próprio uso), valores literais embutidos em código não apresentam problemas. Porém,
talvez seja necessário um script maior, especialmente um script usado na configuração de empresas. Nessas situações, literais podem resultar em, pelo menos, dois problemas: •
Confusão. Em um script pequeno, pode estar evidente que 1048576 é o valor necessário para converter bytes (o valor retornado da propriedade FreeSpace) em megabytes. Em um script maior, que inclua várias equações matemáticas, isso pode não estar tão evidente. Esse problema ocorre principalmente em configurações de empresas, onde vários administradores podem usar -- e modificar -- o mesmo script. Embora seja fácil para você saber o que 1048576 representa, talvez não seja tão evidente para outro administrador encarregado de modificar o script.
•
Mais trabalho e mais risco de erro. Se você tem certeza de que seu script nunca será alterado, talvez não seja relevante que o uso de literais possa ser confuso. Porém, se houver possibilidade de alteração no script, os valores literais não só serão confusos, como também exigirão mais trabalho para a pessoa que estiver modificando o script. Por exemplo, considere que esse mesmo procedimento -- converter quilobytes em megabytes -- seja usado 5 ou 6 vezes em um script. Se mais tarde você decidir converter o valor em gigabytes em vez de megabytes, você terá de modificar corretamente cada linha de código em que ocorrer a conversão. Se não fizer isso, o script não fornecerá resultados precisos.
Uma maneira de evitar os problemas que podem surgir devido ao uso de literais é utilizar constantes. Constantes são similares a variáveis, pois ambas são locais para armazenar dados. Porém, ao contrário das variáveis, as constantes, depois que são definidas (isto é, depois que um valor é atribuído a elas), não podem ser modificadas durante a execução do script. Ao atribuir itens importantes, como o valor necessário para converter bytes em megabytes, a uma constante, você pode garantir que o valor permanecerá o mesmo: um valor de constante não pode ser alterado, nem inadvertidamente nem de qualquer outra forma. Na listagem 5, uma constante chamada CONVERSION_FACTOR é definida na linha 1 e o valor 1048576 é atribuído a ela. Posteriormente no script (linha 4), o número de bytes de espaço livre em disco é convertido no número de megabytes de espaço livre em disco. Em vez de usar o valor literal 1048576, a constante CONVERSION_FACTOR
é utilizada. Ambas as equações retornam o mesmo resultado; porém, é mais fácil ler e compreender a equação da listagem 5. Listagem 5 Usando constantes 1 Const CONVERSION_FACTOR = 1048576 2 Set objWmiService = GetObject("winmgmts:") 3 Set objLogicalDisk = objWmiService.Get("Win32_LogicalDisk.DeviceID='C:'") 4 FreeMegaBytes = objLogicalDisk.FreeSpace / CONVERSION_FACTOR 5 FreeMegaBytes = Int(FreeMegaBytes) 6 WScript.Echo FreeMegaBytes Outro benefício da utilização de constantes é que elas podem ser definidas uma vez e usadas várias vezes no mesmo script. Por exemplo, uma versão expandida do script mostrado na listagem 5 pode exigir que você converta bytes em megabytes várias vezes durante a execução do script. Em vez de usar o valor literal em cada equação, use a constante. Se mais tarde você decidir converter bytes em gigabytes, precisará somente alterar o valor da constante; não será necessário alterar o valor usado em cada equação. Seqüências de caracteres À medida que você escreve scripts cada vez mais sofisticados, começa a encontrar tipos diferentes de dados (esse tópico é abordado em mais detalhes no livro). Na listagem 5, por exemplo, você precisou usar dados numéricos para atribuir o valor literal 1048576 à constante CONVERSION_FACTOR: Const CONVERSION_FACTOR = 1048576 Essa linha de código será executada corretamente, pois um valor numérico está sendo atribuído à constante. Sempre que você atribuir um valor numérico a uma variável ou a uma constante, digite o sinal de igual seguido do valor. No entanto, resultados inesperados poderão ocorrer se você tentar atribuir um valor alfanumérico (geralmente chamado de valor de seqüência de caracteres) usando a mesma abordagem. Por exemplo, o código a seguir tenta atribuir a seqüência de caracteres atl-dc-01 à variável Computer e, em seguida, exibir o valor da variável: Computer = atl-dc-01 Wscript.Echo Computer Quando esse script for executado, o valor mostrado na figura 4 será exibido.
Figura 4
Como o valor -1 foi atribuído à variável Computer? Quando o VBScript encontra um conjunto de caracteres alfanuméricos que não está entre aspas duplas, ele pressupõe que os caracteres representam o nome de uma variável. Se ele vir um hífen "perdido", presumirá que representa um sinal de menos. Como resultado, ele interpretará a linha Computer = atl-dc-01 como à variável Computer será atribuído: •
O valor da variável atl
•
Menos o valor da variável dc
•
Menos o valor 01
Como atl e dc são exibidas como novas variáveis que não foram inicializadas, o valor 0 será atribuído a elas. Dessa forma, o VBScript interpretará essa linha de código como se estivesse escrita assim: Computer = 0 - 0 - 1 Por isso a atribuição errônea de -1. Quando você atribui um valor de seqüência de caracteres a uma variável ou a uma constante, deve colocá-lo entre aspas duplas; essa é a única forma de assegurar que o VBScript tratará a seqüência de caracteres como um valor alfanumérico e não como uma variável. Por exemplo, esse código atribui corretamente a seqüência de caracteres atl-dc-01 à variável Computer e, em seguida, exibe os resultados: Computer = "atl-dc-01" Wscript.Echo Computer Quando esse script for executado, a seqüência de caracteres mostrada na figura 5 será exibida.
Figura 5 Seqüências de caracteres como variáveis Freqüentemente, as seqüências de caracteres são usadas para atribuir valores a variáveis. Por exemplo, os scripts usados até agora neste capítulo empregam o seguinte código para conectarem-se à WMI: Set objWmiService = GetObject("winmgmts:") Sem explicar todos os detalhes da conexão com a WMI (para obter essas informações, consulte o capítulo sobre a WMI no livro), esse código sempre conecta você ao computador local. Isso é suficiente, a menos que você seja um administrador de
sistema responsável pelo gerenciamento de alguns computadores remotos. Nesse caso, é aconselhável usar um script que possa recuperar o espaço livre em disco de um computador remoto. Isso permitirá a você verificar, a partir da sua estação de trabalho, o espaço em disco disponível em qualquer computador sob o seu controle. Com a WMI, é possível conectar-se a um computador remoto simplesmente incluindo o nome do computador como parte do identificador de origem GetObject. Por exemplo, esta linha de código conecta você ao serviço WMI no computador remoto atl-dc-01: Set objWmiService = GetObject("winmgmts://atl-dc-01") Você pode usar o código precedente para escrever um script que faça a conexão com o computador remoto. Porém, em uma configuração de empresa, talvez você deseje um script mais flexível que possa conectar-se a qualquer computador remoto. Para isso, edite o script sempre que executá-lo, substituindo o nome embutido em código do computador pelo nome embutido em código do computador de destino. Uma alternativa ainda melhor é fornecer alguma maneira para o script aceitar entradas quando estiver sendo executado e assim operar, por exemplo, em um computador inserido como um argumento de linha de comando. A entrada do usuário será discutida posteriormente neste artigo. No entanto, antes de começar essa discussão, é importante compreender como os valores de seqüência de caracteres (como nomes de computador) podem ser atribuídos a uma variável e, em seguida, utilizados como parte do código de script. Por exemplo, na linha 2 da listagem 6, o valor da seqüência de caracteres atl-dc-01 é atribuído à variável Computer. Na linha 3, essa variável é usada para fazer a conexão com o serviço WMI no computador atl-dc-01. Porém, isso não é feito embutindo-se em código o valor atl-dc-01 no identificador de registro, mas sim através do valor da variável Computer. Listagem 6 Usando seqüências de caracteres 1 Const CONVERSION_FACTOR = 1048576 2 Computer = "atl-dc-01" 3 Set objWmiService = GetObject("winmgmts://" & Computer) 4 Set objLogicalDisk = objWmiService.Get("Win32_LogicalDisk.DeviceID='C:'") 5 FreeMegaBytes = objLogicalDisk.FreeSpace / CONVERSION_FACTOR 6 FreeMegaBytes = Int(FreeMegaBytes) 7 WScript.Echo FreeMegaBytes Em um pequeno script de demonstração como esse, usar uma variável para o nome do computador provavelmente exige mais esforço do que embutir o valor em código. Porém, esse script ilustra um conceito importante: você pode atribuir um valor a uma
variável e usá-la no lugar de um valor embutido em código. Por que isso é importante? Imagine que esse script foi criado para recuperar espaço livre em disco de 100 computadores. Em vez de embutir em código seqüências de caracteres separadas do identificador de registro da WMI em cada computador, é possível criar uma única seqüência de caracteres com a variável Computer. Em seguida, o script poderá executar essa única seqüência de caracteres 100 vezes, a cada vez substituindo o valor de Computer por um nome de computador diferente. Porém, no momento, você só precisa se concentrar na linha 3: Set objWmiService = GetObject("winmgmts://" & Computer) É desta forma que o VBScript interpreta essa linha de código: 1. O VBscript lê tudo até a segunda aspa dupla. Em outras palavras: Set objWmiService = GetObject("winmgmts://" 2. Ele lê o E comercial, que significa basicamente "acrescentar o próximo item à seqüência de caracteres precedente". O que vem depois do E comercial é a variável Computer, à qual foi atribuída o valor atl-dc-01. O VBScript vê a linha da seguinte forma: Set objWmiService = GetObject("winmgmts://atl-dc-01" 3. Ele lê o caractere de parêntese de fechamento. O VBScript exige que você tenha um número igual de parênteses de abertura e de fechamento. Se o parêntese de fechamento não estiver incluído, você receberá uma mensagem de erro. Agora, o VBScript lê a linha de código como Set objWmiService = GetObject("winmgmts://atl-dc-01") 4. Após chegar ao final da linha, o VBScript executa a instrução. Por sua vez, o script se conecta ao serviço WMI em atl-dc-01. Para conectar-se ao serviço WMI em um computador diferente, você só precisa alterar o valor da variável Computer. Concatenando seqüências de caracteres Concatenação refere-se ao processo de combinar duas ou mais seqüências de caracteres em uma única seqüência de caracteres (também é possível combiná-las
com valores numéricos ou de datas). A concatenação é usada com freqüência para fornecer saída mais significativa e legível. Por exemplo, o script mostrado na listagem 4 retorna um valor como 10340. Essa informação é bastante útil, desde que você tenha certeza de que o script foi desenvolvido para retornar o número de megabytes de espaço livre em disco da unidade C. Caso você não conheça a função do script, a saída será sem sentido. Entre outras funções, a concatenação ajuda a fornecer contexto para sua saída de script. Por exemplo, em vez de exibir o valor 10340, é aconselhável exibir uma mensagem similar a "Há 10340 megabytes de espaço livre em disco". Para fazer isso, você pode combinar os três itens a seguir: •
"Há ", uma seqüência de caracteres simples representando o início da mensagem.
•
FreeMegaBytes, a variável contendo o número de megabytes livres na unidade.
•
" megabytes de espaço livre em disco.", uma segunda seqüência de caracteres representando o final da mensagem.
Conforme mostrado nas linhas 3, 7 e 8 da listagem 7, você concatena itens no VBScript usando o E comercial (&). Listagem 7 Concatenando seqüências de caracteres 1 Const CONVERSION_FACTOR = 1048576 2 Computer = "atl-dc-01" 3 Set objWmiService = GetObject("winmgmts://" & Computer) 4 Set objLogicalDisk = objWmiService.Get("Win32_LogicalDisk.DeviceID='C:'") 5 FreeMegaBytes = objLogicalDisk.FreeSpace / CONVERSION_FACTOR 6 FreeMegaBytes = Int(FreeMegaBytes) 7 WScript.Echo "Há " & FreeMegaBytes & _ 8 " megabytes de espaço livre em disco." Observação O sublinhado (_) no final da linha 7 é conhecido como o caractere de continuação de linha e é usado para indicar uma quebra na instrução. Isso significa que as linhas 7 e 8 devem ser tratadas como uma única linha. Por ser muito grande para caber no espaço reservado, a linha foi quebrada. As quebras de instrução são abordadas em mais detalhes no livro. Como alternativa, você pode ter atribuído o valor "Há " a uma variável chamada MessageStart e a seqüência de caracteres " megabytes de espaço livre em disco." a
uma variável chamada MessageEnd. Em seguida, você pode ter concatenado as três variáveis da seguinte maneira: Wscript.Echo MessageStart & FreeMegaBytes & MessageEnd Se você observar as linhas 7 e 8, perceberá que os espaços em branco foram embutidos em código nos valores da seqüência de caracteres "Há " e " megabytes de espaço livre em disco.". Isso é necessário, pois o E comercial não insere espaços entre os itens sendo concatenados. Por exemplo, exclua os espaços em branco, desta forma: WScript.Echo "Há" & FreeMegaBytes & "megabytes de espaço livre em disco." Nesse caso, a mensagem resultante executará os três valores juntos, conforme mostrado na figura 6.
Figura 6 Para formas simples de concatenação, você pode evitar esse problema usando uma vírgula em vez do E comercial para combinar os valores: WScript.Echo "Há", FreeMegaBytes, "megabytes de espaço livre em disco." Quando itens são separados por vírgula, um espaço em branco é inserido automaticamente entre eles. Como resultado, a mensagem é formatada de maneira apropriada, conforme mostrado na figura 7.
Figura 7 Coleções Até este ponto do artigo, os scripts foram criados para recuperar o espaço livre na unidade C de um computador especificado. Determinar o espaço livre em uma única unidade é uma tarefa administrativa comum, especialmente quando você está trabalhando com estações de trabalho de usuários que possuem somente uma unidade. Como a intenção era recuperar apenas o espaço livre em disco da unidade C, o DeviceID foi embutido em código no script. É claro que, provavelmente, outros computadores -- incluindo a maioria dos servidores -- possuem várias unidades. Para esses computadores, a determinação do espaço livre na unidade C não é informação suficiente; como administrador do sistema, você também precisa conhecer o espaço livre da unidade D, da unidade E e das outras unidades instaladas no computador. (Na verdade, a classe Win32_LogicalDisk pode identificar e retornar as propriedades de todos os tipos de unidade, incluindo disquetes, CD-ROMs e unidades de rede mapeadas.)
Porém, isso apresenta um problema imediato: como saber quais unidades estão instaladas em um determinado computador? Teoricamente, você pode verificar o espaço livre das unidades C a Z, mas, se um computador não possuir, por exemplo, uma unidade E, o script falhará. Embora seja possível incluir um código criado para tratar esses erros e impedir que o script falhe, o script resultante seria muito longo, dificultando a sua leitura e a sua manutenção. Esse script específico também seria muito ineficiente; mesmo que um computador tivesse somente uma unidade, o script tentaria recuperar o espaço livre nas unidades D a Z inexistentes. Felizmente, objetos de automação quase sempre retornam informações na forma de coleções. Como coleções de selos ou de moedas, essas coleções de automação são simples grupos de itens relacionados. Por exemplo, o script da listagem 8 usa o método InstancesOf da WMI (linha 4) para retornar não apenas uma unidade específica, mas uma coleção consistindo em todos os discos lógicos instalados no computador. Se o computador tiver quatro unidades (C, D, E e F), a coleção terá quatro itens, um para cada unidade. Listagem 8 Usando coleções 1 Const CONVERSION_FACTOR = 1048576 2 Computer = "atl-dc-01" 3 Set objWmiService = GetObject("winmgmts://" & Computer) 4 Set colLogicalDisks = objWmiService.InstancesOf("Win32_LogicalDisk") 5 For Each objLogicalDisk In colLogicalDisks 6 FreeMegaBytes = objLogicalDisk.FreeSpace / CONVERSION_FACTOR 7 FreeMegaBytes = Int(FreeMegaBytes) 8 WScript.Echo objLogicalDisk.DeviceID & " " & FreeMegaBytes 9 Next Obter informações retornadas como uma coleção significa que você não precisa antecipar quais unidades estão instaladas ou não em um computador. Em vez disso, simplesmente pergunte pela coleção (todas as instâncias de unidades de disco instaladas no computador). Depois que a coleção tiver sido retornada, você poderá usar um loop For Each (também conhecido como um loop de iteração) para examinar cada item individual da coleção. For Each A instrução For Each fornece uma maneira simples de iterar todos os itens em uma coleção (ou em uma matriz). Ao contrário da instrução For (que será abordada
posteriormente), For Each não exige que você saiba quantos itens existem na coleção. Em vez disso, ela inicia com o primeiro item da coleção (ou matriz) e continua até que tenha efetuado um loop em cada item. Um loop For Each típico tem a seguinte aparência: For Each objLogicalDisk In colLogicalDisks WScript.Echo objLogicalDisk.DeviceID Next Os itens individuais que compõem esse loop são descritos na tabela 2. Tabela 2 Item
Descrição
objLogicalDisk
Variável que representa as instâncias de unidade de disco individuais.
colLogicalDisks
Nome dado à coleção de unidades de disco recuperada com a WMI.
For Each objLogicalDisk in
Inicia o loop. A sintaxe básica pode ser lida como
colLogicalDisks
Instância For Each de um objeto em uma coleção de objetos executa uma ação. Neste exemplo, isso pode ser lido como "Para cada unidade de disco individual na coleção de unidades de disco instalada neste computador … "
Wscript.Echo
Instruções executadas para cada unidade de disco na
objLogicalDisk.DeviceID
coleção (neste exemplo, há somente uma instrução, mas pode haver várias instruções entre as instruções For Each e Next). Observe que a referência a unidades de disco individuais é feita com a variável objLogicalDisk e com a propriedade adequada (neste caso, DeviceID). O valor dessa propriedade será alterado todas as vezes através do loop. Por exemplo, em um computador com unidades C, D e E, objLogicalDisk.DeviceID será igual a C na primeira iteração, pois C é o DeviceID da primeira unidade da coleção. Em passagens subseqüentes através do loop, objLogicalDisk.DeviceID será igual a D e, em seguida, a E.
Next
Indica o final do loop. Depois de iterar cada item da coleção, o script prosseguirá na linha após a instrução Next. Se não houver linhas após essa instrução, o script será finalizado.
Coleções sem itens É possível que uma coleção não contenha itens. Por exemplo, considere este script, que retorna o conjunto de todas as unidades de fita instaladas em um computador: Set objWmiService = GetObject("winmgmts:") Set colTapeDrives = objWmiService.InstancesOf("Win32_TapeDrive") For Each objTapeDrive In colTapeDrives WScript.Echo objTapeDrive.Name Next Se esse script for executado em um computador sem unidades de fita, parecerá que nada aconteceu. Na verdade, o script será executado conforme o esperado. Porém, como o computador não possui uma unidade de fita, a coleção resultante de todas as unidades de fita instaladas no computador não conterá itens. Quando executado em um computador sem unidades de fita, o script irá: 1. Conectar-se ao serviço WMI. 2. Recuperar a coleção de unidades de fita instalada no computador. 3. Configurar um loop For Each para percorrer toda a coleção, exibindo o nome de cada unidade de fita individual da coleção. Porém, como não há itens na coleção, o loop For Each e as instruções nele incluídas não serão de fato executados. Em vez disso, o loop For Each será ignorado e o script irá para a primeira linha após a instrução Next. Nesse script de exemplo, não há linhas de código após a instrução Next, logo, o script é finalizado. Infelizmente, isso pode ser confuso: não existe maneira óbvia de saber se o script foi executado ou não. Uma forma de aprimorar esse script é usar a propriedade Count para determinar a quantidade de itens na coleção. Por exemplo, esse script usa a propriedade Count para exibir o número de unidades de fita instaladas em um computador:
Set objWmiService = GetObject("winmgmts:") Set colTapeDrives = objWmiService.InstancesOf("Win32_TapeDrive") Wscript.Echo colTapeDrives.Count O seu script pode usar a propriedade Count para determinar o número de itens da coleção e executar uma das seguintes opções: •
Exibir as propriedades do item, caso haja um ou mais itens na coleção.
•
Exibir uma mensagem como "Não há unidades de fita instaladas neste computador.", caso a coleção não contenha itens.
O script poderá ter esta aparência (o uso da instrução If-Then-Else será explicado posteriormente neste artigo): Set objWmiService = GetObject("winmgmts:") Set colTapeDrives = objWmiService.InstancesOf("Win32_TapeDrive") If colTapeDrives.Count = 0 Then Wscript.Echo "Não há unidades de fita instaladas neste computador." Else For Each objTapeDrive In colTapeDrives WScript.Echo objTapeDrive.Name Next End If Loop Você já viu uma forma de loop quando usou a instrução For Each do VBScript. Embora a instrução For Each seja a forma ideal de iteração através de uma coleção ou de uma matriz, outros cenários podem garantir uma construção de loop mais flexível. Por exemplo, scripts que monitoram ou medem recursos de sistema normalmente precisam coletar dados em intervalos periódicos. É improvável que você verifique o espaço livre em disco momentos após instalar um novo disco rígido e depois nunca mais verifique o espaço livre ainda disponível na unidade. Em vez disso, é provável que você verifique o espaço livre em disco em intervalos regulares, talvez uma vez por semana, uma vez por dia, ou a de hora em hora, dependendo do computador que está sendo monitorado (por exemplo, servidores de correio normalmente usam espaço em disco de maneira mais rápida do que outras estações de trabalho do usuário).
Se houver um período de tempo relativamente longo entre coleções de dados, é aconselhável executar o script como uma tarefa agendada. Dessa forma, você pode agendar o script para ser executado todas as manhãs, às 2:00, e nunca mais se preocupar com o assunto. Porém, usar tarefas agendadas não é sempre uma opção. Por exemplo, digamos que você deseje medir o uso do processador em um computador. Além disso, você deseja medir esse uso a cada 10 segundos até coletar 500 amostras. Embora, teoricamente, você possa criar 500 tarefas agendadas, uma após a outra, isso resulta em muito mais trabalho. Uma abordagem mais adequada é executar um único script que colete todas as 500 amostras. Uma maneira de fazer com que um único script execute o mesmo conjunto de comandos várias vezes é incluir esses comandos em um loop For. Com um loop For, é possível executar um conjunto de comandos um determinado número de vezes. Por exemplo, o script mostrado na listagem 9 verifica de hora em hora por 12 horas o espaço livre em disco em um computador. Para isso, uma instrução For é usada na linha 7 indicando que o loop deve ser executado 12 vezes. As linhas 8-14 representam o corpo do loop For e determinam o espaço livre em disco de cada unidade de disco do computador. A linha 14 interrompe o script por uma hora (por meio de uma constante que interrompe o script por 3.600.000 milissegundos) e a linha 15 é simplesmente a instrução Next, que marca o final do loop. Quando o script for executado, uma conexão será estabelecida com o computador remoto atl-dc-01. O script recuperará e exibirá as informações de espaço livre em disco e, em seguida, fará uma interrupção de uma hora. Após o término dessa interrupção, o script executará um loop e recuperará as informações sobre espaço livre em disco uma segunda vez. Esse processo continuará até que as informações de espaço em disco tenham sido recuperadas 12 vezes. Em seguida, o script executará a linha de código após a instrução Next. Como não há linhas de código após essa instrução, o script será finalizado. Listagem 9 Executando comandos várias vezes 1 Const CONVERSION_FACTOR = 1048576 2 Const ONE_HOUR = 3600000 3 Computer = "atl-dc-01" 4 5 Set objWmiService = GetObject("winmgmts://" & Computer) 6 7 For i = 1 to 12
8 Set colLogicalDisk = objWmiService.InstancesOf("Win32_LogicalDisk") 9 For Each objLogicalDisk In colLogicalDisk 10 FreeMegaBytes = objLogicalDisk.FreeSpace / CONVERSION_FACTOR 11 FreeMegaBytes = Int(FreeMegaBytes) 12 WScript.Echo objLogicalDisk.DeviceID & " " & FreeMegaBytes 13 Next 14 Wscript.Sleep ONE_HOUR 15 Next For A instrução For permite executar um bloco de código um determinado número de vezes. Ela não deve ser confundida com a instrução For Each. A instrução For Each é usada para iterar os itens individuais em uma coleção (ou em uma matriz). A instrução For é usada para executar um conjunto específico de instruções um determinado número de vezes. Para usar a instrução For, é necessário determinar um ponto inicial e um ponto final. Como instruções For normalmente são criadas para executar um conjunto de instruções X vezes, você iniciará com 1 e terminará com X. Portanto, para executar a mesma ação dez vezes, inicie com 1 e termine com 10. Observação Você pode escolher um ponto inicial arbitrário (por exemplo, 314 ou 6.912) e concluir com o ponto final apropriado (324 ou 6.922). Porém, será mais fácil ler e manter seu código se você iniciar com 1 e terminar com 10. A instrução For exige que você use uma variável de loop (também chamada de contador) que mantém um cálculo contínuo informando quantas vezes o loop foi executado. Por exemplo, a variável i é usada como o contador no código a seguir. O contador iniciará em 1 e executará as linhas de código contidas no corpo da instrução For. Após as instruções terem sido executadas, o contador aumentará automaticamente em 1, significando que i é agora igual a 2. O script retornará automaticamente ao início da instrução For e verificará se o valor 2 ainda está no intervalo válido. Como ele está, o corpo da instrução For será executado uma segunda vez. For i = 1 To 5 Wscript.Echo i Next Wscript.Echo "Loop For concluído."
O que acontecerá se i for igual a 6? O script retornará automaticamente ao início do loop For e verificará se 6 faz parte do intervalo válido. Como não faz, o loop For será imediatamente finalizado e a execução do script continuará na primeira linha após a instrução Next. A saída do script terá a seguinte aparência: 1 2 3 4 5 Loop For concluído. Observação Haverá vezes em que você desejará executar o mesmo conjunto de instruções continuamente; porém, não será possível determinar antecipadamente quantas vezes será necessário executar o código. Por exemplo, digamos que você deseje verificar o espaço livre em disco uma vez por hora e que deseje continuar executando essa verificação até que o espaço em disco fique abaixo do espaço especificado. Nesse caso, você deseja que o script inicie e continue a ser executado até que o espaço em disco fique abaixo do limite, independentemente da quantidade de iterações necessária para executar essa ação. Em situações como essa, é aconselhável usar um loop Do (discutido no livro). Tomando decisões Um dos principais motivos para a utilização de scripts como ferramentas de administração de sistema é o fato de que eles reduzem a necessidade de intervenção humana. Os scripts introduzidos até o momento neste capítulo tentam atingir esse objetivo; a versão do script mostrado na listagem 8, por exemplo, pode conectar-se a qualquer computador (mesmo remoto), conectar-se à WMI e determinar o espaço livre em disco de cada unidade lógica instalada no computador. Executando esse script regularmente, os administradores poderão receber uma notificação antecipada caso alguma unidade esteja com pouco espaço em disco. Porém, ainda é tarefa do administrador do sistema analisar a saída do script e determinar se um disco está ou não com pouco espaço. O script pode ser aprimorado através do exame de espaço e da emissão de uma notificação somente quando o espaço livre está abaixo do nível especificado. Com essa abordagem, os administradores só serão notificados se um disco estiver com pouco espaço. Se não
houver notificações, é porque todos os discos estão em conformidade com os padrões e nenhuma ação será necessária. O VBScript fornece várias construções de programação que permitem aos scripts "tomarem decisões". Isso significa que um script pode analisar alguns dados e, em seguida, executar uma ação especificada com base no valor dos dados. A forma mais simples do código de tomada de decisão é a instrução If. Com a instrução If, o script examina o valor de um dado específico, comparando-o a um limite pré-determinado (por exemplo, se o espaço livre em disco é menor do que 100 megabytes). Se a instrução for verdadeira (que seria o caso se somente 99 megabytes de espaço em disco estivessem disponíveis), o script executará uma ação. Se a instrução não for verdadeira, nenhuma ação será executada. Esse tipo simples de tomada de decisão é mostrado na listagem 10. Na linha 11, o script verifica se o espaço livre é menor do que 100 megabytes (isso é feito através da comparação entre o valor e a constante WARNING_THRESHOLD). Se essa instrução condicional for verdadeira (por exemplo, se uma unidade tiver somente 99 megabytes de espaço livre), a instrução imediatamente após a construção If será executada. Neste exemplo, a instrução seguinte é a linha 12, que exibe a mensagem de que a unidade tem pouco espaço em disco. Se a instrução condicional for falsa (por exemplo, se a unidade tiver 101 megabytes de espaço livre em disco), a linha 12 não será executada. Em vez disso, o processamento será transferido para a linha 13, que marca o final da instrução If, e continuará na linha 14. Listagem 10 Tomando decisões 1 Const CONVERSION_FACTOR = 1048576 2 Const WARNING_THRESHOLD = 100 3 Computer = "atl-dc-01" 4 5 Set objWmiService = GetObject("winmgmts://" & Computer) 6 Set colLogicalDisks = objWmiService.InstancesOf("Win32_LogicalDisk") 7 8 For Each objLogicalDisk In colLogicalDisks 9 FreeMegaBytes = objLogicalDisk.FreeSpace / CONVERSION_FACTOR 10 FreeMegaBytes = Int(FreeMegaBytes) 11 If FreeMegaBytes < WARNING_THRESHOLD Then 12 WScript.Echo objLogicalDisk.DeviceID & " tem pouco espaço em disco."
13 End If 14 Next Executando várias ações usando If-Then-Else O script mostrado na listagem 10 exibirá uma mensagem de aviso se uma unidade tiver pouco espaço em disco. Porém, se a unidade de disco tiver espaço livre adequado, nenhuma mensagem será exibida. Para um script simples de monitoração, isso é aceitável. Por outro lado, o usuário que estivesse executando esse script, não teria como saber se a falta de saída havia ocorrido porque todas as unidades possuíam espaço em disco adequado ou porque a execução do script havia falhado por algum motivo. Em outras palavras, às vezes é necessário que o script avalie uma condição e, em seguida, execute uma ação diferente com base nessa avaliação. Por exemplo, talvez você deseje exibir uma mensagem de aviso quando a unidade tiver pouco espaço em disco e uma mensagem "Sem problemas" quando a unidade tiver espaço em disco adequado. Esse tipo de abordagem pode ser implementado com a instrução If-ThenElse. A função da instrução If-Then-Else está implícita em seu nome. Se (If) uma condição for verdadeira (ou falsa), execute esta ação. Caso contrário (Else), execute esta ação. Se houver pouco espaço em disco, ecoe uma mensagem de aviso. Caso contrário, ecoe a mensagem "Sem problemas". Um exemplo disso é mostrado na listagem 11. Na linha 11, o espaço livre em disco de uma unidade é comparado a um limite de aviso. Se a instrução condicional for verdadeira (isto é, se o espaço livre em disco for menor do que o limite de aviso), a linha 12 será executada. E se a instrução condicional for falsa? Para lidar com essa possibilidade, uma cláusula Else foi incluída na linha 13. Se a instrução condicional for falsa e a unidade tiver espaço adequado, a linha 14, linha imediatamente após a cláusula Else, será executada. Listagem 11 Usando uma instrução If-Then-Else 1 Const CONVERSION_FACTOR = 1048576 2 Const WARNING_THRESHOLD = 100 3 Computer = "atl-dc-01" 4 5 Set objWmiService = GetObject("winmgmts://" & Computer)
6 Set colLogicalDisks = objWmiService.InstancesOf("Win32_LogicalDisk") 7 8 For Each objLogicalDisk In colLogicalDisks 9 FreeMegaBytes = objLogicalDisk.FreeSpace / CONVERSION_FACTOR 10 FreeMegaBytes = Int(FreeMegaBytes) 11 If FreeMegaBytes < WARNING_THRESHOLD Then 12 WScript.Echo objLogicalDisk.DeviceID & " tem pouco espaço em disco." 13 Else 14 WScript.Echo objLogicalDisk.DeviceID & " tem espaço em disco adequado." 15 End If 16 Next É possível construir cenários mais elaborados, cenários que possam executar mais do que apenas duas ações possíveis. Formas diferentes de construir esses cenários são discutidas no System Administration Scripting Guide. Matrizes Coleções são uma forma excelente de empacotar informações, pois permitem trabalhar com vários itens, mesmo que você não conheça os detalhes sobre esses itens. Por exemplo, o script introduzido na listagem 8 permite recuperar o espaço livre em disco de todas as unidades instaladas em um computador, mesmo que você não saiba quantas unidades estão instaladas no computador. Para executar uma ação em cada item da coleção, simplesmente use um loop For Each para iterar em toda a coleção e execute a ação em todos os itens, um por um. Objetos de automação podem criar coleções automaticamente. Porém, pode haver outras informações, não retornadas por um objeto de automação, que serão mais fáceis de manipular se você puder iterar no conjunto de itens um por um. Por exemplo, digamos que você deseje verificar o espaço livre em disco disponível em três computadores e não apenas em um. Você pode escrever o código para verificar o primeiro computador, copiar e colar esse código e, em seguida, modificar o código colado para verificar o espaço livre em disco no segundo computador. É possível repetir esse processo para verificar o espaço livre em disco no terceiro computador. Embora essa abordagem funcione, ela logo se tornará tediosa, especialmente se você precisar verificar, por exemplo, 100 computadores. Além disso, digamos que você precise alterar o código, talvez retornando não apenas o espaço livre na unidade, mas também o tamanho total da unidade. Para fazer essa alteração, seria necessário
alterar todas as 100 instâncias, um processo que levaria muito tempo e aumentaria a possibilidade de erro. Uma abordagem mais adequada seria usar um loop For Each e percorrer uma lista de computadores, verificando o espaço livre em disco de cada um. Para fazer isso, devese colocar os nomes dos computadores em uma matriz, uma estrutura de dados que pode ser usada praticamente da mesma forma que uma coleção. O script mostrado na listagem 12 coloca os nomes de três computadores (atl-dc-01, atl-dc-02 e atl-dc-03) em uma matriz e usa um loop For Each para conectar-se a cada computador e recuperar as informações de espaço livre em disco. Na linha 3, uma matriz chamada Computers é criada. Isso é feito com a função Array, através da especificação dos nomes dos três computadores como os parâmetros da função (os nomes são colocados entre aspas, pois são seqüências de caracteres). Na linha 5, um loop For Each é usado para percorrer todos os elementos da matriz Computers. Listagem 12 Usando matrizes 1 Const CONVERSION_FACTOR = 1048576 2 Const WARNING_THRESHOLD = 100 3 Computers = Array("atl-dc-01", "atl-dc-02", "atl-dc-03") 4 5 For Each Computer In Computers 6 7 Set objWmiService = GetObject("winmgmts://" & Computer) 8 Set colLogicalDisks = objWmiService.InstancesOf("Win32_LogicalDisk") 9 10 For Each objLogicalDisk In colLogicalDisks 11 FreeMegaBytes = objLogicalDisk.FreeSpace / CONVERSION_FACTOR 12 FreeMegaBytes = Int(FreeMegaBytes) 13 If FreeMegaBytes < WARNING_THRESHOLD Then 14 WScript.Echo Computer & " " & objLogicalDisk.DeviceID & _ 15 " tem pouco espaço em disco." 16 End If 17 Next 18 19 Next Embora matrizes possam parecer similares a coleções, pelo menos no contexto da instrução For Each, existe uma diferença importante. Uma matriz é uma lista de valores simples e indexada e uma coleção é um objeto de automação, baseado em
COM e completamente desenvolvido. Isso afeta o modo como os dois tipos de lista são criados e como itens de lista individuais podem ser acessados. Por exemplo, você deve usar a palavra-chave Set para criar uma coleção (linha 8) da mesma forma como faria com qualquer objeto de automação. As matrizes não possuem esses requisitos, pois não são objetos de automação. Um número de índice é atribuído a cada elemento de uma matriz. No VBScript, o número de índice 0 é atribuído ao primeiro elemento de uma matriz e os números 1, 2, 3 etc. são atribuídos aos elementos subseqüentes. Logo, a matriz criada no script anterior conteria os números de índice e os elementos mostrados na tabela 3. Observe que o número de índice mais alto será sempre uma unidade menor do que o número de elementos da matriz. Tabela 3 Número de índice Elemento 0
atl-dc-01
1
atl-dc-02
2
atl-dc-03
Você pode usar esses números de índice para acessar elementos individuais na matriz. Por exemplo, essa linha de código exibirá atl-dc-02, o valor do número de índice 1 e o segundo elemento da matriz: Wscript.Echo Computers(1) Para exibir o valor de um item diferente na matriz, substitua o valor 1 pelo número de índice apropriado. Métodos adicionais para criar matrizes e acessar os elementos individuais dessas matrizes são abordados no System Administration Scripting Guide. Entrada O script mostrado na listagem 12 foi criado para uma empresa que não espera alterações na infra-estrutura de computação, já que essa infra-estrutura já está estabelecida. Uma infra-estrutura estática como essa é a exceção e não a regra. A maioria das empresas possui um ambiente mais dinâmico; embora somente três servidores (atl-dc-01, atl-dc-02, atl-dc-03) precisem de monitoração no momento, não há garantias de que somente esses três servidores precisarão de monitoração posteriormente. Itens embutidos em código, como nomes de computador nos scripts, ocasionam dois problemas relacionados:
•
Falta de flexibilidade. O script da listagem 12 recuperará somente informações sobre o espaço em disco disponível nos computadores atl-dc-01, atl-dc-02 e atl-dc-03. Se você precisar recuperar espaço livre em disco para o computador atl-dc-04, será necessário modificar o script.
•
Atualizações freqüentes. O script da listagem 12 foi criado para recuperar informações sobre o espaço livre em disco de um conjunto específico de computadores (por exemplo, todos os controladores de domínio em uma localização específica). Sempre que um novo controlador de domínio for adicionado ou sempre que um controlador de domínio existente for retirado, o script precisará ser atualizado. Se você usar somente esse script em sua empresa, isso talvez não cause problemas. Porém, se usar vários scripts, você provavelmente perderá mais tempo modificando-os do que economizará usando-os.
Há várias formas de se permitir que os usuários insiram informações, como nomes de servidor, em um script (para obter mais detalhes sobre vários desses métodos, consulte o System Administration Scripting Guide). Talvez a maneira mais fácil seja fazer com que os usuários especifiquem essas informações como argumentos sempre que o script for executado. Um argumento (também conhecido como parâmetro) é a informação fornecida junto com o comando que de fato executa o script. Por exemplo, digamos que você normalmente inicie um script da seguinte maneira: cscript DiskSpace.vbs Um argumento é qualquer informação extra adicionada ao final do comando. Por exemplo, esse comando possui três argumentos, um para cada nome de computador: cscript DiskSpace.vbs atl-dc-01 atl-dc-02 atl-dc-03 Além de fornecer argumentos, o script deve incluir o código que usa esses argumentos. Esse tipo de código é abordado em detalhes no capítulo 3 do System Administration Scripting Guide. Um exemplo simples também é mostrado na listagem 13. Na linha 9 desse script, um loop For Each é estabelecido para percorrer o conjunto de argumentos fornecido na inicialização do script. Nesse script, cada argumento é atribuído sucessivamente à variável Computer e, em seguida, usado para estabelecer conexão com o serviço WMI no computador (linha 11). Com base na linha de comando de exemplo acima, na primeira vez que o loop For Each for executado, o valor atl-dc01será atribuído a Computer. Em iterações subseqüentes, os valores atl-dc-02 e atldc-03 serão atribuídos a Computer.
Listagem 13 Obtendo entrada de usuário 1 Const CONVERSION_FACTOR = 1048576 2 Const WARNING_THRESHOLD = 100 3 4If WScript.Arguments.Count = 0 Then 5 WScript.Echo "Uso: DiskSpace.vbs servidor1 [servidor2] [servidor3] ..." 6 WScript.Quit 7 End If 8 9 For Each Computer In WScript.Arguments 10 11 Set objWmiService = GetObject("winmgmts://" & Computer) 12 Set colLogicalDisks = objWmiService.InstancesOf("Win32_LogicalDisk") 13 14 For Each objLogicalDisk In colLogicalDisks 15 FreeMegaBytes = objLogicalDisk.FreeSpace / CONVERSION_FACTOR 16 FreeMegaBytes = Int(FreeMegaBytes) 17 If FreeMegaBytes < WARNING_THRESHOLD Then 18 WScript.Echo Computer & " " & objLogicalDisk.DeviceID & _ 19 " tem pouco espaço em disco." 20 End If 21 Next 22 23Next Uma vantagem em usar argumentos é o fato de que eles são colocados automaticamente em uma coleção (Wscript.Arguments). Isso torna mais fácil percorrer os argumentos fornecidos a um script: você simplesmente configura um loop For Each e itera cada argumento da coleção, exatamente da mesma forma como itera as unidades de disco individuais em uma coleção de unidades de disco. Como argumentos são colocados em uma coleção, também é fácil verificar quantos argumentos, se houver, foram fornecidos quando o script foi iniciado. Na linha 4 do script, Wscript.Arguments.Count é usado para determinar a quantidade de argumentos fornecida (o número de argumentos fornecido será igual ao número de itens da coleção de argumentos). Se a contagem for igual a 0, significando que nenhum argumento foi fornecido, um conjunto de instruções de utilização será exibido e o script será finalizado (com o método Wscript.Quit).
Tratamento de erros O script mostrado na listagem 13 é bastante arriscado. Digamos que o usuário tenha inserido um nome de servidor inválido como um argumento. Quando o script tentar se conectar a esse computador inexistente, falhará e a mensagem de erro "The remote server machine does not exist or is unavailable" será exibida. Claro que uma determinada porcentagem de risco é inerente a todos os scripts usados até o momento neste artigo, incluindo os scripts em que os nomes de computador foram embutidos em código. Afinal, o script não pode distinguir entre um nome de computador inválido e um nome de computador válido que, por algum motivo, não está disponível na rede. Por exemplo, digamos que você execute o script da listagem 12 e que o computador chamado atl-dc-01 esteja off-line no momento. Neste ponto, o script falhará e não será mais processado. Isso significa que você não só falhará ao recuperar o espaço livre em disco no computador atl-dc-01, como também falhará ao recuperar o espaço livre em disco nos computadores atl-dc-02 e atl-dc-03, mesmo que eles estejam conectados à rede e funcionando corretamente. Isso ocorre pois o script é finalizado antes de tentar se conectar a atl-dc-02 ou atl-dc-03. A incapacidade em se conectar ao computador atl-dc-01 é um exemplo de erro em tempo de execução, que ocorre após o script ter sido iniciado (por comparação, um erro de sintaxe, como uma palavra-chave incorreta, é gerado e o script é finalizado antes que as linhas de código sejam de fato executadas). Para obter ajuda na proteção contra erros em tempo de execução, você pode incluir a instrução de tratamento de erros do VBScript, On Error Resume Next, em seus scripts. Sem o tratamento de erros, um script é finalizado imediatamente quando encontra um erro em tempo de execução. Com o tratamento de erros, o script não é finalizado, em vez disso, ele tenta executar a linha seguinte do script. O script procede desta maneira, ignorando as linhas que geram erros e executando as linhas que não geram erros. Tratamento de erros com o objeto Err On Error Resume Next permite que o script continue funcionando caso ocorra um erro em tempo de execução. Porém, isso pode causar pelo menos dois problemas. Por um lado, nenhuma mensagem de erro é gerada para informar que ocorreu erro. Se executar um script e nada ocorrer, você não terá como saber onde houve falha.
Por outro lado, talvez você prefira que um script não tente executar todas as linhas caso ocorra erro em tempo de execução. Por exemplo, considere um script que siga este procedimento: 1. Conecta-se a um computador remoto. 2. Copia um conjunto de arquivos do computador local para o computador remoto. 3. Exclui o conjunto de arquivos original do computador local. Digamos que você tenha executado esse script, mas que o computador remoto não esteja disponível. Veja a seguir uma seqüência possível de eventos. 1. O script tenta se conectar ao computador remoto e falha. Porém, On Error Resume Next assegura que o script continue sendo executado. 2. O script tenta copiar arquivos para o computador remoto. A operação falha, pois o computador remoto não está acessível. 3. O script exclui os arquivos do computador local. Infelizmente, essa ação é bemsucedida, pois o computador local está disponível. Como resultado, os arquivos são excluídos do computador local, mas não são copiados para o computador remoto. Felizmente, você pode usar o objeto Err intrínseco do VBScript para determinar se o erro ocorreu ou não, e caso tenha ocorrido, para executar a ação apropriada. O objeto Err é criado automaticamente sempre que você executa um script (há somente um objeto Err por instância de script). Esse objeto contém várias propriedades, incluindo as três mostradas na tabela 4. Sempre que o script encontra um erro em tempo de execução, essas propriedades são preenchidas automaticamente com as informações que identificam o erro. Tabela 4 Propriedade
Descrição
Description
Descrição do erro. A descrição pode ser usada para informar ao usuário que ocorreu erro. Isso pode ser realizado com o eco do valor: Wscript.Echo Err.Description
Number
Número inteiro que identifica de forma exclusiva o erro ocorrido. Esse número pode representar um número de erro intrínseco do
VBScript ou um número de erro derivado de um objeto de automação (números de erro do objeto de automação são conhecidos como SCODE, abreviatura para código de status). Para determinar a origem do número de erro, use a propriedade Source. Source
Nome da classe ou identificador programático (ProgID) do objeto que causou o erro. Normalmente, quando o VBScript é responsável pelo erro, a mensagem "Microsoft VBScript runtime error" é exibida como a origem. Se um objeto de automação for responsável pelo erro, você verá o ProgID (por exemplo, "Word.Application").
Quando um script é iniciado, o valor padrão 0 (sem erros) é atribuído à propriedade Number. Caso um erro seja encontrado, o valor da propriedade Number é alterado. Isso permite a você verificar periodicamente se o script encontrou erros. Por exemplo, talvez você deseje verificar o status de erro após tentar se conectar a um computador remoto. Se Err.Number for igual a 0, nenhum erro terá ocorrido. Se Err.Number não for igual a zero, terá ocorrido algum tipo de erro e você poderá supor que a tentativa de conexão com o computador remoto falhou. Como resultado, o script executará uma ação com base no fato de que o computador remoto não estava disponível. Esse tipo de tratamento de erro é implementado no script mostrado na listagem 14. Na linha 1 do script, o tratamento de erros é ativado com a instrução On Error Resume Next do VBScript. Na linha 11, o script usa um loop For Each para percorrer uma lista de nomes de servidor. Na linha 12, o script tenta se conectar a cada um desses servidores. Mas o que ocorre se um desses servidores não está acessível? Conforme observado, na linha 12 o script tenta se conectar a um desses servidores remotos. Se a conexão for bem-sucedida, nenhum erro será gerado, significando que Err.Number permanecerá igual a 0. Porém, se a conexão falhar, um erro será gerado e Err.Number será alterado para refletir o número atribuído ao erro. Se a tentativa de conexão na linha 12 falhar, On Error Resume Next garantirá que o script tente executar a linha 13. Na linha 13, o script verifica o valor de Err.Number. Se o valor for diferente de 0 (significando que um erro ocorreu), o script exibirá Err.Description e, em seguida, reiniciará o loop com o próximo nome de servidor. Se o valor for 0, isso significa que a conexão foi bem-sucedida. Em seguida, o script recupera o espaço livre em disco do computador remoto.
Listagem 14 Tratamento de erros 1 On Error Resume Next 2 3 Const CONVERSION_FACTOR = 1048576 4 Const WARNING_THRESHOLD = 100 5 6 If WScript.Arguments.Count = 0 Then 7 WScript.Echo "Uso: DiskSpace.vbs servidor1 [servidor2] [servidor3] ..." 8 WScript.Quit 9 End If 10 11 For Each Computer In WScript.Arguments 12 Set objWmiService = GetObject("winmgmts://" & Computer) 13 If Err.Number 0 Then 14 WScript.Echo Computer & " " & Err.Description 15 Err.Clear 16 Else 17 Set colLogicalDisks = _ 18 objWmiService.InstancesOf("Win32_LogicalDisk") 19 For Each objLogicalDisk In colLogicalDisks 20 FreeMegaBytes = objLogicalDisk.FreeSpace / CONVERSION_FACTOR 21 FreeMegaBytes = Int(FreeMegaBytes) 22 If FreeMegaBytes < WARNING_THRESHOLD Then 23 WScript.Echo Computer & " " & objLogicalDisk.DeviceID & _ 24 " tem pouco espaço em disco." 25 End If 26 Next 27 End If 28 Next Se você executar o script da listagem 14 e um dos servidores não estiver on-line, o objeto Err e suas propriedades serão preenchidos como mostrado na tabela 5. Tabela 5 Propriedade
Valor
Err.Description
The remote server machine does not exist or is unavailable
Err.Number
462
Err.Source
Microsoft VBScript runtime error
Limpando erros A linha 15 do script usa o método Clear para redefinir explicitamente as propriedades do objeto Err. Isso é importante, pois caso essa redefinição não ocorra, essas propriedades só serão alteradas quando outro erro ocorrer. Os valores da propriedade não são alterados quando não ocorrem erros. Como resultado, o script pode agir de forma não apropriada com base na noção errônea de que ocorreu erro. Isso é o que acontecerá se você não redefinir explicitamente as propriedades do objeto Err. Quando um script é iniciado, o objeto Err apresenta o número padrão 0 e as propriedades de descrição e de origem vazias. Se o script não puder se conectar ao computador atl-dc-01, as propriedades do objeto Err serão definidas como mostrado na tabela 5. Isso funciona conforme o esperado. Porém, o que acontece quando o computador efetua um loop e tenta se conectar ao computador atl-dc-02? Nesse caso, a tentativa é bem-sucedida e nenhum erro é gerado. No entanto, como nenhum erro foi gerado, o objeto Err ainda contém os valores de propriedade mostrados na tabela 5, pois esse objeto só é atualizado quando ocorre um erro. Por sua vez, o script verifica que 462 é o número do erro, o valor restante da tentativa malsucedida de conexão com o computador atl-dc-01. Como 462 não é igual a 0, o script executa uma ação com base na decisão incorreta de que um erro ocorreu e, portanto, o computador atl-dc-02 deve estar inacessível. Esse mesmo problema ocorre quando o script tenta recuperar espaço livre em disco no computador atl-dc-03. O método Clear supera esse problema redefinindo o objeto Err para os valores padrão (number igual a 0, source e description definidas como vazio). Como os valores são redefinidos, eles refletirão corretamente o fato de que nenhum erro ocorreu quando o script tentar recuperar espaço livre em disco para o computador atl-dc-02. Aviso de isenção de responsabilidade da versão Beta Esta documentação é uma versão antecipada da documentação final e pode ser alterada substancialmente antes da versão comercial final. Além disso, é informação confidencial de propriedade da Microsoft Corporation. Ela é divulgada conforme descrito no acordo de não-divulgação estabelecido entre o adquirente e a Microsoft. Este documento é fornecido somente para fins informativos e a Microsoft não oferece
quaisquer garantias, explícitas ou implícitas, neste documento. As informações contidas neste documento, incluindo o URL e outras referências ao site da Internet na Web, estão sujeitas a alterações sem aviso prévio. O usuário assume inteiro risco quanto ao uso e aos resultados do uso deste documento. Salvo indicação em contrário, os exemplos de empresas, organizações, produtos, pessoas e acontecimentos aqui mencionados são fictícios. Nenhuma associação com qualquer empresa, organização, produto, pessoa ou acontecimento real é intencional ou deve ser inferida. Obedecer a todas as leis de direitos autorais aplicáveis é responsabilidade do usuário. Sem limitar os direitos autorais, nenhuma parte deste documento pode ser reproduzida, armazenada ou introduzida em um sistema de recuperação, ou transmitida de qualquer forma por qualquer meio (eletrônico, mecânico, fotocópia, gravação ou qualquer outro), ou para qualquer propósito, sem a permissão expressa, por escrito, da Microsoft Corporation. A Microsoft pode ter patentes ou requisições para obtenção de patente, marcas comerciais, direitos autorais ou outros direitos de propriedade intelectual que abrangem o conteúdo deste documento. A posse deste documento não lhe confere nenhum direito sobre as citadas patentes, marcas comerciais, direitos autorais ou outros direitos de propriedade intelectual, salvo aqueles expressamente mencionados em um contrato de licença, por escrito, da Microsoft. Trabalho não publicado. © 2002 Microsoft Corporation. Todos os direitos reservados.