Ei, Equipe de Scripts!Adrenalina pura

A Equipe de Scripts da Microsoft

Fica evidente para nós que escrever para a TechNet Magazine é o trabalho de maior prestígio – e mais gratificante – que alguém pode ter. (É claro que seria ainda mais gratificante se fôssemos pagos, mas essa já é uma outra história.) E que prestígio esse trabalho dá? Coloquemos as coisas desta forma: neste exato momento, em todas as partes do mundo, crianças que estão indo dormir olham para suas mães e dizem: "mamãe, quando crescer, quero escrever uma coluna mensal sobre scripts na TechNet Magazine".

Observação Evidentemente, no mundo todo, algumas pessoas já pensam que esta coluna é escrita por crianças. Mas essa também é uma outra história.

É bem sabido que a Equipe de Scripts gosta de ser paparicada por conta da coluna na TechNet Magazine. Chegamos, inclusive, a aprender como lidar com os fãs em busca de autógrafos e com os paparazzi. Mas a verdade é que não queremos realizar esse trabalho pela honra e pela glória; fazemos esse trabalho pela adrenalina pura de escrever scripts para a administração do sistema.

Convenhamos, não é sempre que você lê os termos "adrenalina pura" e scripts para a administração do sistema na mesma frase. (Isso, é claro, a menos que "adrenalina pura" seja precedida de "ausência total ou completa de".)

Em geral, as pessoas consideram os scripts para a administração do sistema extremamente úteis, mas é bem provável que não muito interessantes. Na verdade, elas acham os scripts meio monótonos. E eis o porquê: nenhuma delas tentou escrever scripts de dados de configuração da inicialização no Windows Vista® ou no Windows Server® 2008.

Ahá! Isso fez o seu coração palpitar, não fez? Como a maior parte dos leitores deste artigo já deve saber, no Windows Vista e no Windows Server 2008, o arquivo boot.ini antigo deu lugar a um novo armazenamento de dados de configuração da inicialização que fornece mais flexibilidade (e recursos) quando se é preciso gerenciar o processo de inicialização.

Isso é bem legal. Mas legal mesmo é: graças a um novo provedor WMI (Instrumentação de Gerenciamento do Windows®), o armazenamento BCD (Dados de Configuração da Inicialização) agora pode ser acessado facilmente – e gerenciado por completo – usando scripts.

Não se preocupe com essa estranha sensação que acabou de percorrer sua espinha. Isso é adrenalina pura. Depois de começar a trabalhar com scripts BCD, você se acostumará com eles.

Antes de prosseguirmos, devemos salientar que somos incapazes de sequer começar a abordar tudo o que se pode fazer usando o provedor BCD, pelo menos não nesta única coluna. (Enviamos um email para os editores da revista aventando a possibilidade de fazermos uma edição especial dupla dedicada inteiramente a como escrever scripts de dados de configuração da inicialização, mas ainda não tivemos nenhuma resposta.)

Caso queira obter informações mais completas, consulte a documentação do provedor WMI BCD em go.microsoft.com/fwlink/?LinkId=116953. Enquanto isso, mostraremos um código de exemplo projetado para computadores de inicialização múltipla – computadores com mais de um sistema operacional instalado.

Ah, esses scripts só funcionam no Windows Vista e no Windows Server 2008. Isso porque, como mencionamos anteriormente, esses são os únicos dois sistemas operacionais que oferecem suporte ao BCD.

Comecemos observando um script que nos informa qual sistema operacional um computador está usando no momento. É verdade, não se trata do uso mais interessante para o provedor BCD. Afinal, já podemos usar a classe WMI Win32_OperatingSystem para determinar qual é o sistema operacional usado por um computador no momento. No entanto, esse é um script relativamente simples (pelo menos em relação aos scripts BCD), além de proporcionar uma forma interessante de ilustrar as técnicas básicas necessárias ao trabalho com o BCD. (As técnicas são, no mínimo, um pouquinho… incomuns.)

Além disso, não podemos dar muita emoção a nossas colunas: a TechNet Magazine já nos avisou de que seremos responsabilizados por eventuais danos causados por fãs ensandecidos e superfervorosos da Ei, Equipe de Scripts! Considerando a balbúrdia generalizada irrompida em todo o mundo após a publicação da nossa coluna sobre expressões regulares, bem, não podemos correr o risco de voltar a fazer algo tão incrível.

Observação Você se lembra daqueles vídeos dos Beatles sendo atacados por fãs e daquelas imagens das garotas desmaiando e chorando quando viam John, Paul, George e Ringo? É mais ou menos o que acontece conosco sempre que publicamos uma nova coluna.

Está certo, bem, talvez isso seja um pouco de exagero. Mas é claro que muitas pessoas – tanto homens quanto mulheres – suspiram ao ler uma das nossas colunas.

De qualquer forma, observe o script na Figura 1, que usa o provedor BCD para determinar qual é o sistema operacional usado por um computador no momento. Antes de tentar executá-lo, você deve saber que é preciso estar em execução como administrador, ou haverá falha no script.

Figura 1 Conhecendo o sistema operacional atual

Const BcdLibraryString_Description = &h12000004
Const Current = "{fa926493-6f1c-4193-a414-58f0b2456d1e}"

strComputer = "."

Set objStoreClass = GetObject("winmgmts:{(Backup,Restore)}\\" & _
 strComputer & "\root\wmi:BcdStore")

objStoreClass.OpenStore "", objStore
objStore.OpenObject Current, objDefault

objDefault.GetElement BcdLibraryString_Description, objElement
Wscript.Echo "Current operating system: " & objElement.String

E não, isso não significa que basta estar conectado a uma conta com privilégios de administrador. Isso quer dizer que você precisa abrir uma janela de prompt de comando clicando com o botão direito do mouse em Prompt de Comando no menu Iniciar e selecionando Executar como administrador. Só assim é possível executar esse script no prompt de comando.

Então, como isso funciona? Sabe, estávamos receosos de que você perguntar. Mas, tudo bem, tentaremos explicar da melhor forma possível (que, não bastasse, deve esfriar as coisas, pelo menos por um tempo).

Começamos definindo duas constantes: BcdLibraryString_Description e Current. BcdLibraryString_Description se refere ao objeto que queremos recuperar; nesse caso, esse objeto contém Description (nome) do sistema operacional atual.

Aliás, essa é uma das doces peculiaridades do trabalho com o provedor BCD. Normalmente, você não apenas recupera o valor de uma propriedade, e sim usa um desses valores de constantes (além do método GetElement) para recuperar outro objeto e, em seguida, o valor de uma propriedade que pertença a esse objeto. É claro que isso é meio bobo, mas você sabe o que eles dizem: chegar lá é só metade da diversão.

Observação O tipo faz você se preocupar com aonde eles estavam indo, não é?

O mesmo acontece com a constante Current, bem, se trata de um GUID que representa o sistema operacional em uso atualmente. O valor

 {fa926493-6f1c-4193-a414-58f0b-2456d1e} 

é considerado um GUID "bem conhecido" (que, não bastasse, prova que as pessoas na Microsoft realmente têm senso de humor).

Apesar do fato desse GUID ser bem conhecido, fomos além e incluímos o valor mesmo assim, apenas caso algum dos leitores deste artigo não consiga se lembrar de qual destes valores está correto:

{fa926493-6f1c-4193-a414-58f0b2456d1e} 
{fa926493-6f1c-4193-a414-58f0b2456d1f}

Observação Caso você esteja se perguntando, GUID pode ser pronunciado como "gwid" ou "goo-id". Poderíamos dar mais informações como o fato de que o GUID anterior deve ser V1, vendo como o terceiro grupo de dígitos começa com 4. Mas, fizemos uma promessa de tentar e manter o entusiasmo ao máximo. E cumprimos as nossas promessas.

Como talvez tenha imaginado, você precisará usar constantes, valores hexadecimais e GUIDs em todos os lugares ao trabalhar com o provedor BCD. Não podemos abordar todos esses itens na coluna deste mês, mas você pode visitar a página do BCD que mencionamos anteriormente no MSDN® (go.microsoft.com/fwlink/?LinkId=116953) para obter mais informações. E se você consegue suportar tamanho entusiasmo, aí está.

Depois de definir as nossas duas constantes, nos conectamos ao serviço WMI no computador local. É possível usar esse script para recuperar os dados de configuração da inicialização de uma máquina remota? Claro que sim.

Sinceramente, se não fosse possível, o valor desse negócio de BCD seria apenas mínimo. Para recuperar os dados de configuração da inicialização de uma máquina remota (mais uma vez, Windows Vista ou Windows Server 2008 deve estar em execução no computador remoto), basta atribuir o nome da máquina à variável strComputer:

strComputer = "atl-fs-001"

Também devemos salientar alguns itens importantes da nossa cadeia de conexão da WMI. Para começar, você talvez tenha percebido que incluímos privilégios de backup e de restauração em nossa cadeia de conexão; é isso o que a construção {(Backup,Restore)} faz. Isso é importante? Bem, caso você queira que o script funcione, isso é muito importante: dessa forma, se você não incluir explicitamente esses dois privilégios, haverá falha no script.

Segundo, observe que não nos conectamos ao namespace root\cimv2, o mais usado em scripts de administração do sistema. Na verdade, nos conectamos ao namespace root\WMI e nos associamos diretamente à classe BCDStore. É essa a função desse trecho de código:

"\root\wmi:BcdStore" 

E não, essa não era a parte legal. Ela ainda está por vir.

Muito embora possa haver uma ou outra exceção uma aqui, outra ali, qualquer script BCD escrito irá, no geral, começar com as mesmas três etapas: definir as constantes, se conectar ao serviço WMI e abrir o armazenamento do BCD. Já concluímos as etapas 1 e 2. A seguinte linha de código se refere à etapa 3:

objStoreClass.OpenStore "", objStore

Como dissemos, aqui estamos abrindo o armazenamento BCD, a entidade de sistema operacional que armazena todas as informações de configuração da inicialização. Para abrir o armazenamento, basta chamarmos o método OpenStore, passando a ele dois parâmetros:

  • uma cadeia de caracteres vazia ("") Isso informa ao script que queremos abrir o armazenamento padrão.
  • objStore. Trata-se de um parâmetro "de saída" que fornecemos ao script. Damos ao método o nome de uma variável e, em sinal de gratidão, o método retorna um objeto (nesse caso, um objeto que representa o armazenamento BCD) que usa o nome da variável como uma referência de objeto.

Assim que o armazenamento é aberto, podemos usar o método OpenObject para recuperar mais um outro objeto (armazenado no parâmetro de saída objDefault):

objStore.OpenObject Current, objDefault

E que novo objeto é esse? É isso mesmo: a versão do sistema operacional atualmente em uso. Isso é algo que conhecemos porque passamos a OpenObject a constante Current, o GUID bem conhecido que representa o sistema operacional atual.

Tudo bem, então agora sabemos qual é o sistema operacional atualmente em uso no computador, certo? Bem, quase. Para obter essas informações, ainda precisamos usar GetElement para recuperar um objeto que represente a descrição desse sistema operacional:

objDefault.GetElement _
  BcdLibraryString_Description, objElement

Agora, você promete que não se entusiasmará demais e sairá em meio a uma bagunça generalizada? Muito bem. Nesse caso, podemos contar que agora é possível recuperar o valor da propriedade String e – finalmente! – determinar o sistema operacional atualmente em uso no computador:

Wscript.Echo "Current operating system: " _
  & objElement.String

Por favor, mantenha a calma. Lembre-se da sua promessa: nada de bagunça generalizada. Sim, sabemos o quanto é difícil. Apenas faça o melhor que puder. Tente respirar bem fundo. Isso sempre funciona conosco quando estamos escrevendo scripts BCD.

Como dissemos, há muitos problemas a serem enfrentados apenas para determinar qual é o sistema operacional em uso em um computador. Há formas muito mais fáceis de realizar essa tarefa. No entanto, o lado bom é que agora você compreende como funciona um script BCD, o que significa ser possível fazer coisas que os escritores de scripts jamais puderam fazer. (Calma, calma!) Por exemplo, em computador de inicialização múltipla, um sistema operacional permanece sempre marcado como sendo o "padrão". Se um computador for reiniciado e não houver nenhum outro, o computador carregará automaticamente o sistema operacional padrão. Antes do Windows Vista (e o provedor BCD), não havia como um criador de scripts determinar o sistema operacional padrão de um computador. Mas agora isso é tão fácil quanto executar um script como o mostrado na Figura 2.

Figura 2 Determinando o sistema operacional padrão

Const BcdLibraryString_Description = &h12000004
Const BootMgrId = "{9dea862c-5cdd-4e70-acc1-f32b344d4795}"
Const DefaultType = &h23000003

strComputer = "." 

Set objStoreClass = GetObject("winmgmts:{(Backup,Restore)}\\" & _
    strComputer & "\root\wmi:BcdStore")
objStoreClass.OpenStore "", objStore

objStore.OpenObject BootMgrId, objBootMgr 

objBootMgr.GetElement DefaultType, objDefaultOSIdentifier
objStore.OpenObject objDefaultOSIdentifier.Id, objDefault

objDefault.GetElement BcdLibraryString_Description, objElement 
WScript.Echo "Default operating system: " & objElement.String

Você tem razão: isso pede um pouco de bagunça generalizada, não é? Tá, mas só um pouquinho, hein? Não explicaremos esse script detalhadamente. Supondo que não tenha ignorado os 10 ou 12 parágrafos anteriores, você deve ser capaz de acompanhar a lógica por conta própria. No entanto, você pode observar que, para identificar o sistema operacional padrão, precisamos executar uma etapa imediata: precisamos usar o método OpenObject para abrir uma instância do objeto Boot Manager. Depois de abrirmos o Gerenciador de Inicialização, podemos usar a constante DefaultType para recuperar um objeto que represente o sistema operacional padrão.

Agora, precisamos admitir que isso é bem interessante: podemos determinar o sistema operacional atual, além do sistema operacional padrão. Mas sabe o que seria bem legal mesmo? O legal seria recuperar uma lista de todos os sistemas operacionais instalados em um computador. Isso sim seria legal! Aperte os cintos e observe a Figura 3.

O que estamos fazendo aqui? Bem, para começar, estamos definindo duas constantes novas: WindowsImages, que permite recuperar instâncias de todos os sistemas operacionais que oferecem suporte ao BCD (ou seja, Windows Vista e Windows Server 2008), e LegacyImages, que permite recuperar instâncias de todos os sistemas operacionais "herdados" no computador. Depois de nos conectarmos ao armazenamento BCD, usamos o método EnumerateObjects para recuperar todas as instâncias dos sistemas operacionais compatíveis com o BCD instalados no computador:

objStore.EnumerateObjects _
  WindowsImages, colObjects 

Figura 3 Localizando todos os sistemas operacionais em um computador

Const BcdLibraryString_Description = &h12000004
Const WindowsImages = &h10200003
Const LegacyImages = &h10300006

strComputer = "."

Set objStoreClass = GetObject("winmgmts:{(Backup,Restore)}\\" & _
 strComputer & "\root\wmi:BcdStore")

objStoreClass.OpenStore "", objStore 

objStore.EnumerateObjects WindowsImages, colObjects 

For Each objObject in colObjects
 objObject.GetElement BcdLibraryString_Description, objElement 
 Wscript.Echo objElement.String
Next
Wscript.Echo

objStore.EnumerateObjects LegacyImages, colObjects 

For Each objObject in colObjects
 objObject.GetElement BcdLibraryString_Description, objElement 
 Wscript.Echo objElement.String
Next

Depois de EnumerateObjects realizar seu trabalho, configuraremos um loop For Each a ser executado em todos os sistemas operacionais nessa coleção. Nesse loop, usamos estas duas linhas de código para recuperar e exibir a descrição do sistema operacional:

objObject.GetElement _
  BcdLibraryString_Description, objElement 
Wscript.Echo objElement.String

E, em seguida, repetimos o processo com todos os sistemas operacionais herdados instalados na máquina.

objStore.EnumerateObjects _
  LegacyImages, colObjects 

For Each objObject in colObjects
 objObject.GetElement _
  BcdLibraryString_Description, objElement 
 Wscript.Echo objElement.String
Next

Observação Compreendemos a emoção envolvida, mas, por favor, execute os scripts BCD com moderação. É provável que haja um limite até o qual o corpo humano pode agüentar a adrenalina. Grávidas, mulheres que podem engravidar, as que não podem, as que já engravidaram, ou mesmo quem não seja mulher, e sim homem, não devem executar scripts BCD sem antes consultar um médico.

Tudo bem, você não precisa consultar o médico primeiro. Mas seria interessante ouvir o que um médico diria se fosse questionado quanto à execução de scripts BCD, não seria?

Agora vamos tentar algo realmente doido: vejamos se conseguimos alterar o sistema operacional padrão. Por exemplo, vamos supor que tivéssemos um computador de inicialização dupla com o Windows Vista e o Windows Server 2008 em execução. E vamos supor que queiramos definir o Windows Vista como sendo o sistema operacional padrão. Como faremos isso? Bem, observe a Figura 4. Ela mostra uma forma de realizar essa tarefa.

Figura 4 Alterando o sistema operacional padrão

Const BootMgrId = "{9dea862c-5cdd-4e70-accl-f32b344d4795}"
Const BcdLibraryString_Description = &h12000004
Const DefaultType = &h23000003
Const WindowsImages = &h10200003

strComputer = "."

Set objStoreClass = GetObject("winmgmts:{(Backup,Restore)}\\" & _
 strComputer & "\root\wmi:BcdStore")

objStoreClass.OpenStore "", objStore 
objStore.EnumerateObjects WindowsImages, colObjects 

For Each objObject in colObjects
 objObject.GetElement BcdLibraryString_Description, objElement 
 If Instr(objElement.String, "Vista") Then
  objStore.OpenObject BootMgrId, objBootMgr 
  objBootMgr.SetObjectElement DefaultType, objObject.ID 
 End If
Next

Com esse script, estamos novamente abrindo o armazenamento BCD e, em seguida, usaremos EnumerateObjects para recuperar uma coleção de todos os sistemas operacionais que reconhecem o BCD instalados no computador. Daí em diante, configuramos um loop For Each a ser executado em todos os itens da coleção, usando a seguinte linha de código (agora já bem familiar) para recuperar a descrição de cada sistema operacional:

objObject.GetElement _
  BcdLibraryString_Description, objElement

Assim que contarmos com a descrição de um determinado sistema operacional, usamos a função InStr para ver se a palavra Vista é exibida em algum lugar desse valor:

If Instr(objElement.String, "Vista") Then

E você tem razão: isso parece um pouco ultrapassado, não parece? A forma mais legal seria usar o GUID do Windows Vista e abrir diretamente esse sistema operacional, sem que fosse necessário enumerar e percorrer todos os sistemas operacionais no computador.

Infelizmente, essa forma exigiria que soubéssemos o GUID do Windows Vista. Na verdade, desse jeito não precisamos saber nada (sempre um bônus para a Equipe de Scripts). Tudo o que precisamos fazer é continuar pesquisando até localizar um sistema operacional com a palavra Vista no título.

Observação E se você tiver várias instâncias do Windows Vista instaladas no computador? Bem, nesse caso, você talvez tenha que procurar uma cadeia de caracteres como Vista Ultimate ou Vista Enterprise.

Assim que localizamos o Windows Vista, usamos estas duas linhas de código para abrir o Gerenciador de Inicialização do Windows e definimos o sistema operacional padrão como, bem, Windows Vista:

objStore.OpenObject BootMgrId, objBootMgr 
objBootMgr.SetObjectElement _
  DefaultType, objObject.ID 

Acabou o espaço que tínhamos para a coluna deste mês. Afinal, até mesmo a Equipe de Scripts não consegue lidar com esse entusiasmo sem fim 24 horas por dia, 7 dias por semana. Mas não se preocupe, pois estaremos de volta no mês que vem com outra edição de Ei, Equipe de Scripts! Até lá, com um pouco de sorte, você já estará recuperado.

O desafio de script do Dr. Scripto

O desafio mensal que testa não apenas sua habilidade de resolver quebra-cabeça, mas também de criar scripts.

Julho de 2008: quadrados do VBScript

Está certo, é mais provável que eles sejam retângulos, e não quadrados, mas isso não está em questão. Para resolver esse quebra-cabeças, encaixe cada quadrado à direita em um espaço vazio à esquerda para formar os nomes das funções do VBScript. Cada quadrado será usado uma vez. Por exemplo:

Para resolver corretamente este exemplo, você precisa mover o quadrado OU (retângulo) até o espaço em branco na primeira palavra, e MS e OX até os quadrados em branco na segunda palavra. Isso resulta nas funções do VBScript UBound e MsgBox, como mostrado aqui:

Agora é sua vez de tentar:

RESPOSTA:

O desafio de script do Dr. Scripto

Resposta: quadrados do VBScript, julho de 2008

A Equipe de Scripts trabalha na – quer dizer, é contratada pela – Microsoft. Quando não estão jogando/treinando/assistindo beisebol (e praticando diversas outras atividades), eles administram o Script Center da TechNet. Confira no site www.scriptingguys.com.

© 2008 Microsoft Corporation e CMP Media, LLC. Todos os direitos reservados; é proibida a reprodução total ou parcial sem permissão.