Ei, Equipe de Scripts!Gerenciamento de desktop do além

A Equipe de Scripts da Microsoft

Faça download do código deste artigo: HeyScriptingGuy2007_11.exe (151KB)

Por conta de um incrível apelo popular, achamos que deveríamos fazer algo um pouco diferente neste mês: em vez de falarmos sobre scripts de administração do sistema, começaremos – deixa para música de suspense – contando uma história de fantasmas!

Observação: tudo bem, então, tecnicamente, se quiséssemos mesmo fazer algo diferente neste mês, começaríamos falando mesmo sobre mudanças nos scripts de administração do sistema. Então, apenas acompanhe a gente, certo? Obrigado!

Há muitos anos, morreu uma das tataravós do script. Pouco tempo após seu enterro em um caixão de madeira simples, o tataravô começou a ter pesadelos terríveis nos quais sua amada esposa tentava sair desesperadamente do túmulo. Após seguidos pesadelos e súplicas repetidas, ele finalmente convenceu as autoridades locais a fazer a exumação do corpo. Quando o caixão foi aberto, todos ficaram horrorizados ao ver que as unhas da tataravó tinham sido entortadas para trás e que o caixão estava cheio de arranhões!

Tudo bem, a história pode não ser toda verídica; na verdade, quanto mais pensamos nela, mais percebemos que ela não tem nada de real. No entanto, fica uma lição muito importante. Não temos a menor idéia de qual seja, mas que ela deixa, ah, deixa.

Um momento, agora, sim, lembramos! Os caixões foram originalmente criados para proteger a pessoa morta dos elementos naturais e para ajudar a impedir a decomposição do corpo. Infelizmente, eles têm uma conseqüência indesejada: possibilitam, mesmo que em teoria, que você enterre uma pessoa viva e tenha a certeza de que ela jamais conseguirá sair. Como mostra claramente a história da tataravó do script, mesmo os planos mais perfeitos podem acabar em tragédias e em pessoas sendo enterradas vivas! (Deixa para a música de suspense mais uma vez.)

Observação: a menos, é claro, que você opte pelo Improved Burial Case, invenção de Franz Vester por volta de 1860. O caixão incluía um barbante amarrado a um sino que permanecia acima do solo; se houvesse um enterro prematuro, bastaria o "finado" tocar o sino e pedir ajuda. O Improved Burial Case também contava com uma escada retrátil, embora nós não saibamos claramente como uma escada retrátil ajudaria a pessoa a sair de um caixão enterrado a sete palmos da terra. Se você fosse enterrado acima da garagem de alguém, aí é claro que uma escada dessas seria muito útil. Caso contrário...

Acontece algo (no que se refere aos planos perfeitos que levam a desastres) bastante semelhante com os firewalls de Internet. (Bem, quase isso.) Os firewalls foram originalmente criados para manter afastadas as pessoas mal-intencionadas: eles bloqueiam o tráfego de entrada da rede, o que ajuda a manter hackers e invasores longe dos computadores. Isso é ótimo, mas – assim como o problema de ser enterrado vivo – também há uma conseqüência indesejada aqui: os firewalls também podem manter afastadas as pessoas bem-intencionadas. Isso fica ainda mais evidente no caso do WMI (Instrumentação de Gerenciamento do Windows®), que depende do DCOM para realizar tarefas administrativas em computadores remotos. Os firewalls tendem a bloquear todo o tráfego DCOM de entrada, algo que dificulta muito (se não torna praticamente impossível) gerenciar programaticamente os computadores na Internet. Na verdade, sem abrir portas adicionais no firewall, o que o torna mais vulnerável a hackers e crackers, isso é muito difícil. A menos, claro, que você opte pelo WinRM: Gerenciamento Remoto do Windows (escada retrátil não incluída).

O que é o Gerenciamento Remoto do Windows?

De acordo com o SDK do WinRM (msdn2.microsoft.com/aa384426), o Gerenciamento Remoto do Windows é "a implementação Microsoft do WS-Management, um protocolo amigável a firewalls com base no protocolo SOAP padrão, que possibilita a interoperação entre hardwares e sistemas operacionais de fornecedores diferentes". Impressionante, não? Como não iremos abordar os detalhes do protocolo WS-Management na coluna deste mês, nós recomendamos a leitura do SDK do WinRM para obter detalhes. Por enquanto, tudo o que nos interessa é a disponibilidade do WinRM no Windows Server® 2003 R2, no Windows Vista® e no Windows Server 2008, além de que ele permita a você gerenciar computadores pela Internet. O WinRM faz isso usando a porta 80, uma porta de serviços da Internet padrão que a maioria dos firewalls deixa aberta. (Porém, a porta usada pelo WinRM e o mecanismo de transporte padrão, HTTP, podem ser alterados conforme a necessidade.)

Nós também não perderemos tempo na coluna deste mês abordando como instalar e configurar o WinRM. Já há muitas informações disponíveis para ajudá-lo a fazer isso (msdn2.microsoft.com/aa384372). Mas vamos parar um momento para enfatizar um ponto importante: caso você queira usar o WinRM para recuperar as informações de um computador remoto (que, é claro, é o motivo principal de uso do WinRM inicialmente), o WinRM deve estar em execução tanto no computador local quanto no computador remoto.

O que isso significa? Bem, isso significa que, se não tiver atualizado os computadores cliente para o Windows Vista (digamos que não!) ou os servidores para o Windows Server 2003 R2 ou o Windows Server 2008, você não achará o WinRM tão útil assim, pelo menos não agora. No entanto, talvez seja desnecessário dizer que esse não deve ser o caso amanhã. (E, é claro, presumindo-se que o firewall permita, sempre é possível usar o WMI e DCOM para gerenciar computadores remotos.)

Retornando todas as propriedades e instâncias de uma classe

Mas quem se importa com limitações e avisos de isenção de responsabilidade, certo? Em lugar dessa confusão toda, vejamos se conseguimos mostrar como escrever um script capaz de usufruir o WinRM. Coincidentemente, acabamos de criar um pequeno script simples que, usando o protocolo HTTP e a porta 80, se conecta a um computador chamado atl-fs-01.fabrikam.com e, em seguida, retorna informações completas sobre todos os serviços instalados no computador. Consulte a Figura 1 para ver o script em pleno funcionamento.

Figure 1 Componentes de projeto do Silverlight

Arquivo Descrição
CreateSilverlight.js Este é um script JScript (em sua versão inicial, o Silverlight só dá suporte a scripts JScript) usado para especificar as configurações iniciais do Silverlight, inclusive o arquivo XAML para configurar a interface do usuário e os objetos gráficos.
SampleProject.js Este é apenas um arquivo em branco no qual é possível agregar funções JScript.
Silverlight.js O arquivo é usado para inicializar o controle Silverlight.
SampleProject.html É onde ocorre toda a diversão. SampleProject.html é apenas um arquivo HTML que inclui códigos para a leitura em três arquivos .js. Ele também inclui um código para criar instâncias do controle Silverlight.
SampleProject.xaml E para que serve isso? Para saber, você precisará voltar ao texto principal desta coluna.
   

Figure 1 Listando serviços em um computador remoto

strComputer = "atl-fs-01.fabrikam.com"

Set objWRM = CreateObject("WSMan.Automation")
Set objSession = objWRM.CreateSession("http://" & strComputer)

strResource = "https://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Service"

Set objResponse = objSession.Enumerate(strResource)

Do Until objResponse.AtEndOfStream
    DisplayOutput(objResponse.ReadItem)
Loop

Sub DisplayOutput(strWinRMXml)
    Set xmlFile = CreateObject("MSXml2.DOMDocument.3.0")    
    Set xslFile = CreateObject("MSXml2.DOMDocument.3.0")
    xmlFile.LoadXml(strWinRMXml)
    xslFile.Load("WsmTxt.xsl")
    Wscript.Echo xmlFile.TransformNode(xslFile)
End Sub

Como você pode ver, começamos atribuindo o nome DNS do computador (atl-fs-01.fabrikam.com) a uma variável chamada strComputer. Também poderíamos criar a conexão usando o endereço IP do computador (ou até mesmo o endereço IPv6). Por exemplo:

strComputer = "192.168.1.1"

Depois de atribuirmos um valor a strComputer, nós criamos uma instância do objeto WSMan.Automation e chamamos o método CreateSession para se conectar ao computador remoto, neste caso, usando o protocolo HTTP (exatamente como dissemos que faríamos):

Set objSession = objWRM.CreateSession _
    ("http://" & strComputer)

Como observamos, queremos retornar informações sobre os serviços instalados no computador remoto. Além disso e, pelo menos para esse primeiro exemplo, queremos informações sobre todas as propriedades de todos os serviços. O que tudo isso significa? Isso significa que precisamos especificar um URI que nos ligue à classe Win32_Service do computador remoto:

strResource = _
  "https://schemas.microsoft.com" & _
  "/wbem/wsman/1/wmi/root/cimv2" & _
  "/Win32_Service"

Certo, não se trata do melhor URI que você já viu. (Mas, pensando bem, não sabemos se nós já vimos algum bom URI.) Porém, felizmente, grande parte do URI é clichê; tudo com o que você precisa se preocupar é o caminho do WMI bem no final:

https://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Service

Isso deve ser bem simples. E se você quisesse se conectar à classe root/cimv2/Win32_Process? Aí, bastaria modificar o caminho do URI de acordo:

https://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Process

Interessado na classe root/default/SystemRestore? Bem, mais uma vez, basta modificar a classe do URI, tomando cuidado para especificar o namespace padrão (e não cimv2):

https://schemas.microsoft.com/wbem/wsman/1/wmi/root/default/SystemRestore

E assim por diante... Também é um pouco constrangedor que você precise incluir a parte https://schemas.microsoft.com/wbem/wsman/1/wmi do URI, mas...

Neste ponto, estamos prontos para obter alguns dados. Para isso, basta chamarmos o método Enumerate, passando a variável strResource como sendo o único parâmetro do método:

Set objResponse = _
  objSession.Enumerate(strResource)

Essa linha de código realmente preencherá objResponse com as informações sobre os serviços instalados no computador atl-fs-01? Pode apostar que sim. No entanto, diferentemente dos scripts WMI padrão, você não obtém uma série de objetos, cada qual com propriedades e métodos de propriedade próprios. Na verdade, você receberá um antigo blob XML grande que se assemelha um pouco ao que vê na Figura 2.

Figure 2 Cores legais

<Canvas
 xmlns="https://schemas.microsoft.com/client/2007"
 xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
 Width="800"
 Height="300">
 
 <Canvas.Background>
 <LinearGradientBrush>
 <GradientStop Color="Blue" Offset="0.0" />
 <GradientStop Color="Black" Offset="1.0" />
 </LinearGradientBrush>
 </Canvas.Background>

</Canvas>

Figure 2 Antigo blob XML grande

<p:Win32_Service xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="
https://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Service" xmlns:ci
m="http://schemas.dmtf.org/wbem/wscim/1/common" xsi:type="p:Win32_Service_Type"
xml:lang="en-US"><p:AcceptPause>false</p:AcceptPause><p:AcceptStop>false</p:Acce
ptStop><p:Caption>Windows Media Center Service Launcher</p:Caption><p:CheckPoint
>0</p:CheckPoint><p:CreationClassName>Win32_Service</p:CreationClassName><p:Desc
ription>Starts Windows Media Center Scheduler and Windows Media Center Receiver
services at startup if TV is enabled within Windows Media Center.</p:Description
><p:DesktopInteract>false</p:DesktopInteract><p:DisplayName>Windows Media Center

Caso você seja um especialista em XML, não há segredos; qualquer um que esteja familiarizado com XML deve ser capaz de analisar e processar essas informações sem muitos problemas (ainda que, nas palavras do SDK do WinRM, elas não estejam no "formato legível"). Mas e se você não for um especialista em XML? Nesse caso, há duas opções. Uma é esperar o próximo mês, quando mostraremos alguns truques sobre como trabalhar com XML do WinRM. E a segunda é fazer o que fizemos em nosso script de exemplo: empregar a transformação XSL instalada com o WinRM.

Transforma-o-quê XSL?

Transformação XSL não é nada além de um modelo que descreve como um arquivo XML deve ser exibido. Uma abordagem completa dos arquivos XSL vai além do que podemos fazer na coluna deste mês – por isso, mesmo uma análise superficial deles ultrapassa até onde é possível ir aqui. Por essa razão, nós não tentaremos explicar como o WsmTxt.xsl (o nome da transformação interna) realmente funciona. Na verdade, nós apenas mostraremos como é possível usá-la no script.

Quando você chama o método Enumerate, o WinRM envia um fluxo de dados XML. A forma mais fácil de trabalhar com esses dados é definindo um loop Do Until que continue em execução até que você chegue ao final do fluxo de dados. É isso o que fazemos aqui:

Do Until objResponse.AtEndOfStream
    DisplayOutput(objResponse.ReadItem)
Loop

Como é possível ver, dentro do nosso loop nós chamamos uma sub-rotina DisplayOutput. Quando chamamos essa sub-rotina, passamos o valor do método ReadItem do fluxo como sendo o parâmetro da sub-rotina. (Como toda essa abordagem implica, o fluxo XML é enviado novamente em partes separadas, e não em um blob de dados grande. Já o nosso script lê os dados XML parte por parte, ou um item por vez.)

Enquanto isso, a sub-rotina DisplayOutput é semelhante ao seguinte:

Sub DisplayOutput(strWinRMXml)
  Set xmlFile = _
    CreateObject("MSXml2.DOMDocument.3.0")    
  Set xslFile = _
    CreateObject("MSXml2.DOMDocument.3.0")
  xmlFile.LoadXml(strWinRMXml)
  xslFile.Load("WsmTxt.xsl")
  Wscript.Echo xmlFile.TransformNode(xslFile)
End Sub

Resumidamente, começamos criando duas instâncias do objeto MSXml2.DOMDocument.3.0. Carregamos o fluxo de dados XML (strWinRMXML) em um objeto e, em seguida, o arquivo XSL (WsmTxt.xsl) em outro objeto. Neste ponto, podemos chamar o método TransformNode para usar as informações contidas no arquivo XSL a fim de formatar e exibir os dados obtidos do fluxo XML.

Sim, é um pouco confuso mesmo. Mas ao menos a saída (ainda que esteja longe de ser perfeita) fica mais fácil de ser lida (consulte a Figura 3).

Figure 3 Texto de pintura

<TextBlock 
 Name="Test"
 FontSize="40"
 FontFamily="Georgia"
 FontWeight="Bold"
 Canvas.Top="20" 
 Canvas.Left="20"
 Text="The TechNet Script Center">

 <TextBlock.Foreground>
 <SolidColorBrush Name="test_brush" Color="red"/>
 </TextBlock.Foreground>

</TextBlock>

Figure 3 Uma versão mais organizada do XML

Win32_Service
    AcceptPause = false
    AcceptStop = true
    Caption = User Profile Service
    CheckPoint = 0
    CreationClassName = Win32_Service
    Description = This service is responsible for loading and unloading user profiles. If this service is stopped or disabled, users will no longer be able to successfully logon or logoff, applications may have problems getting to users' data, and components registered to receive profile event notifications will not receive them.

Como dissemos, isso é bom, mas não necessariamente ótimo, o que já é motivo suficiente para conferir a coluna no mês que vem, quando mostraremos algumas formas para que você manipule a saída XML sozinho.

Retornando as instâncias e as propriedades selecionadas de uma classe

Nem é preciso dizer que tudo isso é muito legal, exceto por um aspecto: isso talvez não reflita totalmente a maneira com que você costuma fazer o seu trabalho. Sim, haverá momentos em que você desejará retornar todas as propriedades de todas as instâncias de uma classe; porém, também haverá situações (talvez em maior número) em que você desejará retornar apenas as propriedades ou as instâncias selecionadas de uma classe. Por exemplo, talvez você queira retornar apenas as informações sobre os serviços em execução, algo que costuma fazer em um script WMI convencional usando um código semelhante a este:

Set colItems = objWMIService.ExecQuery _
  ("Select * From Win32_Service " & _
   "Where State = 'Running'")

Isso é bom. Mas como você modificará a cadeia de caracteres Resource para que ela seja o equivalente a isso?

Bem, honestamente, você não modificará a cadeia de caracteres Resource para que ela seja o equivalente à instrução ExecQuery. Certamente será preciso modificar a cadeia Resource, mas você também precisará fazer outras coisas.

Com isso em mente, vejamos a Figura 4. Trata-se de um script WinRM que retorna informações sobre os serviços em execução em um computador (e não todos os serviços instalados nele).

Figure 4 Truques de TextBlock

<TextBlock.Triggers>
 <EventTrigger RoutedEvent=
     "TextBlock.Loaded">
 <BeginStoryboard>
 <Storyboard>
 <DoubleAnimation
 Storyboard.TargetName="Test"
 Storyboard.TargetProperty="Opacity"
 From="0.0" To="1.0" 
 Duration="0:0:5" />
 </Storyboard>
 </BeginStoryboard>
 </EventTrigger>
</TextBlock.Triggers>

Figure 4 Descobrindo os serviços em execução

strComputer = "atl-fs-01.fabrikam.com"

Set objWRM = CreateObject("WSMan.Automation")
Set objSession = objWRM.CreateSession("http://" & strComputer)

strResource = "https://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/*"
strFilter = "Select * From Win32_Service Where State = 'Running'"
strDialect = "https://schemas.microsoft.com/wbem/wsman/1/WQL"

Set objResponse = objSession.Enumerate(strResource, strFilter, strDialect)

Do Until objResponse.AtEndOfStream
    DisplayOutput(objResponse.ReadItem)
Loop

Sub DisplayOutput(strWinRMXml)
    Set xmlFile = CreateObject("MSXml2.DOMDocument.3.0")    
    Set xslFile = CreateObject("MSXml2.DOMDocument.3.0")
    xmlFile.LoadXml(strWinRMXml)
    xslFile.Load("WsmTxt.xsl")
    Wscript.Echo xmlFile.TransformNode(xslFile)
End Sub

À primeira vista, ele pode parecer totalmente idêntico ao primeiro script WinRM que mostramos a você; no entanto, há algumas diferenças muito importantes. Para ter uma idéia, observe o valor que atribuímos à cadeia de caracteres Resource:

strResource = _
  "https://schemas.microsoft.com" & _
  "/wbem/wsman/1/wmi/root/cimv2/*"

Observe que, ao escrever uma consulta filtrada, nós não especificamos o nome real da classe (Win32_Service) com a qual queremos trabalhar; na verdade, nós apenas nos conectamos ao namespace (root/cimv2) no qual ela reside. Basta se lembrar de acrescentar o asterisco (*) no final. Se você não fizer isso, haverá falha no script com a mensagem "... o nome da classe deve ser '*' (star)", o que quer dizer apenas ser preciso tornar * o nome da classe.

Além disso, também precisamos definir Filter e Dialect:

strFilter = _
  "Select * From Win32_Service " & _
  "Where State = 'Running'"
strDialect = _
  "https://schemas.microsoft.com" & _
  "/wbem/wsman/1/WQL"

Filter deve ser fácil o suficiente para adivinhar; é onde colocamos a nossa consulta WQL (Windows Management Instrumentation Query Language) ("Select * From Win32_Service Where State = 'Running'"). Já Dialect é a linguagem de consulta usada durante a criação de Filter. No momento, só há uma linguagem de consulta permitida: WQL. No entanto, Dialect deve ser especificado, ou haverá falha no script com a observação de que "não há suporte para ... o dialeto de filtro".

Observação: curiosamente, a mensagem de erro sugere que você remova Dialect ao chamar o método Enumerate. Essa é uma recomendação que você não deve seguir. Durante uma consulta filtrada, Dialect deve ser especificado e ser WQL. Ponto final.

A única outra alteração que precisamos fazer ocorre quando chamamos o método Enumerate. Neste ponto, precisamos passar as variáveis que representam Filter (strFilter) e Dialect (strDialect), bem como a variável que representa Resource (strResource):

Set objResponse = _
  objSession.Enumerate _
  (strResource, strFilter, strDialect)

Faça uma tentativa e veja o que acontece.

Agora, que tal retornar apenas as propriedades selecionadas de uma classe? Por exemplo, vamos supor que você esteja interessado em retornar apenas Name e DisplayName de todos os serviços em execução em um computador. O que fazer?

Bem, nesse caso, você pode tentar manipular o XML para que apenas Name e DisplayName sejam exibidos. Embora possível, isso é certamente um pouco confuso. Uma forma mais fácil de fazer isso é especificar apenas essas propriedades durante a atribuição de Filter.

strFilter = _
  "Select Name, DisplayName " & _
  "From Win32_Service " & _
  "Where State = 'Running'"

Faça isso, e tudo o que você terá são Name e DisplayName de cada serviço, assim:

XmlFragment
    DisplayName = Windows Event Log
    Name = EventLog

XmlFragment
    DisplayName = COM+ Event System
    Name = EventSystem

Tudo bem, a formatação está muito simples. (Qual é o problema com esse XmlFragment?) Mais uma razão para conferir a coluna do mês que vem.

Aguarde

Com um pouco de sorte, isso deve ser o suficiente para que você seja apresentado ao maravilhoso e selvagem mundo do WinRM. É claro que não poderíamos encerrar uma coluna sobre o WinRM sem mencionar os "necrotérios de espera" que já foram muito comuns em toda a Alemanha. Nas cidades com necrotérios de espera, os cadáveres não eram enterrados imediatamente. Na verdade, eles eram colocados em salas aquecidas com vários barbantes e fios amarrados aos dedos de suas mãos e de seus pés. A idéia, obviamente, era para que, ao menor sinal de movimento, um alarme fosse disparado e fosse prestada ajuda imediata. Os corpos eram mantidos nesses necrotérios até que ficasse evidente que não havia mais esperanças para essas pessoas e que elas jamais voltariam a fazer algum movimento.

Agora que você tocou no assunto, um necrotério de espera é muito semelhante a ser integrado à Equipe de Scripts, não é? Claro, ninguém jamais ressuscitou em nenhum dos necrotérios de espera, mas as pessoas atribuídas à Equipe de Scripts...

O desafio do script do Dr. Scripto

Em junho de 2007, a Equipe de Scripts participou da conferência Tech•Ed 2007 em Orlando, na Flórida. Não contentes em apenas participar da conferência, decidimos nos divertir um pouco. Mais ainda, achamos que todos também deveriam se divertir um pouco. Com isso em mente, nós levamos o Dr. Scripto's Fun Book, um livreto cheio de quebra-cabeças relacionados a scripts e várias outras informações. Nós nos juntamos à TechNet Magazine – o que significa que pedimos a eles um cantinho do seu estande no Expo Hall – e distribuímos Fun Books para todos os que passavam pelo local.

Como aconteceu, o Fun Book foi um item bastante popular (talvez não tanto quanto os bonecos bobblehead do Dr. Scripto, mas chegou perto). O pessoal bacana e esperto da TechNet Magazine, vendo mais uma chance de aproveitar o sucesso da Equipe de Scripts (já que a própria equipe jamais pareceu ser capaz de aproveitar seu próprio sucesso), pediu para que nós criássemos alguns quebra-cabeças para eles. Quando Jean Ross, da Equipe de Scripts, se virou apenas por alguns instantes, Greg Stemp, também da Equipe, disse: "mas é claro que criaremos!" E aqui vamos nós: o desafio do script do Dr. Scripto. Aproveite.

Scripts para soltar

Nesse quebra-cabeça, todas as letras na seção superior estão embaralhadas e formam um script (em VBScript). Mas não se preocupe, pois você não precisa desembaralhar tudo; na verdade, basta desembaralhar uma coluna por vez. As letras em cada coluna da seção superior preenchem os espaços vazios na mesma coluna da seção inferior. Por exemplo:

Como você pode ver, na coluna 1 nós temos as letras S, C e T. Essas três letras se encaixam na grade abaixo em alguma ordem desconhecida. Mas quando todas elas são soltas na ordem correta, a grade inferior – vista da esquerda para direita – se torna algo lógico. Veja a solução:

É possível ver que as letras S, C e T da coluna 1 são movidas na ordem T, S e C. E elas são as primeiras letras das palavras que formam "The Script Center". O quebra-cabeça real é um pouco mais difícil porque, bem, é maior e por conta do resultado final ser um script completo.

Dica: o script final começa com um caminho completo para um arquivo, é analisado e exibe apenas o nome do arquivo.

Boa sorte!

ANSWER:

O desafio do script do Dr. Scripto

Resposta: Scripts para soltar, novembro de 2007

Neste quebra-cabeça, você precisa soltar os caracteres de uma coluna nas caixas corretas abaixo para que as linhas inferiores criem um script. Eis aqui o script autônomo:

name = "C:\Scripts\Test.txt"
arr = Split(name, "\")
index = Ubound(arr)
Wscript.Echo "Filename: " _
& arr(index)
        

Ele fica assim na grade do quebra-cabeça:

A Equipe de Scripts da Microsoft trabalha para a — bem, é empregada da — Microsoft. Quando não está jogando/treinando/assistindo beisebol (e diversas outras atividades), ela administra o Script Center da TechNet. Confira no site www.scriptingguys.com.

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