Ei, Equipe de Scripts!Nossos jogos do shell favoritos

The Microsoft Scripting Guys

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

De acordo com um antigo provérbio, nem o menor dos pássaros cai na terra sem que Deus saiba. Isso não significa que a Equipe de Scripts esteja sugerindo que as pessoas saiam por aí acertando pardais. (Mas se alguém quiser dar conta daqueles pássaros estúpidos que ficam chiando no telhado às 7h da manhã de sábado... bem , isso é outra história. [O Editor de Scripts gosta de pássaros e, portanto, estamos certos de que ao dizer “dar conta”, o que a Equipe de Scripts que escreve esta coluna realmente quis dizer foi “tomar conta”, para que os pássaros permaneçam fortes e saudáveis .-Ed.]) Contudo, é confortante saber que se você cair, alguém cuidará de você, e que não importa o quão pequeno e insignificante você possa parecer, alguém estará cuidando de você. [Mesmo que seja apenas um editor.-Ed.]

O que é verdade em relação aos pássaros é também para scripts da administração do sistema. É seguro dizer que, no mundo dos scripts, a maior atenção é focalizada nos maiores acontecimentos de script: Windows PowerShellTM, VBScript, WMI, ADSI e até mesmo o FileSystemObject. É compreensível que essas tecnologias obtenham maior atenção e publicidade; afinal de contas, elas permitem que você faça realmente muitas coisas interessantes e úteis. Mas isso não significa que essas sejam as únicas tecnologias disponíveis para autores de script. Longe disso.

Pense no objeto Shell, por exemplo. Embora o objeto Shell possa não ser tão conhecido ou tão amplamente divulgado como o Windows PowerShell, ele também é importante – e útil.

Há uma boa chance de que, cedo ou tarde, alguém solicite que você escreva um script de administração do sistema que utilize o objeto Shell. Isso leva a uma pergunta óbvia: o que exatamente você pode fazer com o objeto Shell? Na verdade, há muitas coisas interessantes que você pode fazer com ele, algumas das quais (como gerenciamento de cotas de disco e exibição de uma barra de progresso quando copiar ou mover arquivos) foram abordadas no Microsoft® Windows® 2000 Scripting Guide (microsoft.com/technet/scriptcenter/guide). Na coluna deste mês, vamos mostrar a você mais uma série de coisas que podem ser feitas com o objeto Shell; ações que provavelmente você não sabia que eram possíveis, muito menos usando o objeto Shell.

Mudando a data da última modificação de um arquivo

Muitos de vocês provavelmente estão lendo o título e pensando “Ei, espere aí. Você não pode alterar a data da última modificação de um arquivo usando um script, pelo menos não com o VBScript”. Em relação a isso, só podemos dizer uma coisa: de onde você tirou essa idéia?

Ah, sim; nós, a Equipe de Scripts, provavelmente já dissemos isso anteriormente, não foi? Bem, acontece que estávamos errados. Chocante! Você pode alterar a data da última modificação de um arquivo usando o VBScript. E tudo que você precisa fazer é usar o objeto Shell.

Observação: não se aborreça pergutando como a Equipe de Scripts pôde se enganar em relação a isso; depois de todos esses anos, isso deveria ser óbvio. Uma pergunta mais interessante seria: como conseguimos fazer algo correto?

Então, você deseja alterar a data da última modificação de um arquivo, certo? Para isso, basta usar este script:

Set objShell = _
  CreateObject("Shell.Application")

Set objFolder = _
  objShell.NameSpace("C:\Scripts")
Set objFolderItem = _
  objFolder.ParseName("Dr_Scripto.jpg")

objFolderItem.ModifyDate = _
  "01/01/2008 8:00:00 AM"

Como você pode ver, não há nada tão complicado nisso. Começamos criando um exemplo do objeto Shell.Application. (Falando nisso, não confunda Shell.Application com Wscript.Shell, o objeto Shell do Host de Scripts do Windows. O objeto Shell que estamos tratando hoje é o objeto Windows Shell.) Depois que nossa instância do objeto Shell estiver funcionando, usamos o método Namespace para fazer a ligação com a pasta C:\Scripts; em seguida, usamos o método estranhamente denominado ParseName para vincular um arquivo específico nessa pasta. Nesse caso, estamos vinculando a uma image JPEG com o nome de arquivo Dr_Scripto.jpg:

Set objFolderItem = _
  objFolder.ParseName("Dr_Scripto.jpg")

E, o que precisamos fazer depois que vinculamos ao próprio arquivo? Isso é fácil; simplesmente atribuímos uma nova data e hora à propriedade ModifyDate:

objFolderItem.ModifyDate = _
  "01/01/2008 8:00:00 AM"

Isso é tudo o que temos de fazer.

Sabe, você têm razão. Isso é muito bom, não? Assim que executarmos o script, a data da última modificação do arquivo será definida como 1º de janeiro de 2008, 8h. (Se você quiser, poderá abrir a pasta C:\Scripts no Windows Explorer para verificar por você mesmo.)

Claro, é possível que alguns de vocês estejam pensando: “Legal. Eu posso mudar a data da última modificação de um arquivo. Mas por que desejo alterar a data da última modificação de um arquivo?”. Bem, várias vezes as pessoas usam a data da última modificação como um tipo de sistema de controle de versão; se você tiver várias cópias de, digamos, um script circulando, uma forma de controlar a versão oficial é verificar a data da última alteração. Ao verificar a data da última modificação, você poderá dizer se uma cópia particular ou não desse script é uma versão não modificada do script original.

Observação: Está bem, certo, alguém pode executar o script que acabamos de mostrar a você e alterar a data da última modificação. Mas apesar de toda a assinatura de código feita por você, alguém sempre pode descobrir uma forma de atingir o sistema. Supondo que você tenha colegas éticos com os quais compartilha scripts, essa abordagem é razoável.

Em algum momento, você pode decidir o que atualizar – e padronizar – a data da última modificação de todos os seus scripts. Como fazer isso? Bem, supondo que todos os seus scripts estejam na pasta C:\Scripts, você pode simplesmente executar a seguinte parte do código:

Set objShell = _
  CreateObject("Shell.Application")

Set objFolder = _
  objShell.NameSpace("C:\Scripts")
Set colItems = objFolder.Items

For Each objItem In colItems
    objItem.ModifyDate  = _
      "01/01/2008 8:00:00 AM"
Next

Como você pode ver, esse script inicia de modo muito parecido com o primeiro script que mostramos. No entanto, nesse caso, depois que efetuamos a ligação com a pasta C:\Scripts, não usamos ParseName para efetuar a ligação a um arquivo individual nessa pasta. Em vez disso, usamos essa linha de código para retornar uma coleção de todos os arquivos encontrados nessa pasta:

Set colItems = objFolder.Items

Assim que tivermos a nossa coleção, vamos configurar um loop For Each para percorrer todos os itens na coleção. Dentro do loop For Each, usamos esta linha de código útil para alterar o valor da propriedade ModifyDate da primeira linha na coleção para 1º de janeiro de 2008, 8h:

objItem.ModifyDate  = _
  "01/01/2008 8:00:00 AM"

E, em seguida, simplesmente executamos o loop e repetimos o processo com o próximo arquivo na coleção. Quando tudo isso tiver sido concluído, todos os arquivos na pasta C:\Scripts (bem, exceto para quaisquer arquivos ocultos) terão exatamente a mesma data da última modificação. Viu como é fácil? Agora, quem disse que você não pode alterar a data da última modificação de um arquivo usando o VBScript?

Ah, sim.

Falando em estar errado...

De volta a tempos remotos, quando a Equipe de Scripts iniciou pela primeira vez o trabalho com script de administração de sistema, não havia como acessar todas as informações de arquivo estendido anexadas a um arquivo no sistema de arquivos NTFS. Por exemplo, se você clicar com o botão direito em um arquivo .wav e, em seguida, clicar em Propriedades, verá informações semelhantes ao que está na Figura 1.

Figura 1 Resumo de propriedades do arquivo

Figura 1** Resumo de propriedades do arquivo **

Como você recupera valores como Taxa de bits ou tamanho da amostra de áudio usando um script? Não é possível fazer isso. Bem, a não ser que você use o objeto Shell. (Ou Windows Desktop Search 3.0, pressupondo que você baixou e instalou esse software.) Em algum momento durante o processo, a capacidade de recuperar todas as informações de propriedade estendida de um arquivo foi adicionada ao objeto Shell, mas de alguma forma a Equipe de Scripts não detectou isso. Conseqüentemente, dizemos às pessoas, “Você não pode usar um script para determinar a taxa de bits de um arquivo .wav”, mas mesmo assim, como mostra o código na Figura 2, você pode.

Figure 2 Use um script para localizar a taxa de bits de um arquivo .wav

Set objShell = CreateObject("Shell.Application")

Set objFolder = objShell.NameSpace("C:\Scripts")
Set objFolderItem = objFolder.ParseName("J0388563.wav")

For i = 0 to 33
    strHeader = objFolder.GetDetailsOf(objFolder.Items, i)
    strValue = objFolder.GetDetailsOf(objFolderItem, i)
    If strValue <> "" Then
        Wscript.Echo strHeader & vbTab & strValue
    End If
Next

Como esse script funciona? Bem, esse script inicia da mesma forma que o primeiro script que lhe mostramos: criamos uma instância do objeto Shell.Application e a vinculamos à pasta C:\Scripts; em seguida, usamos o método ParseName para vincular ao arquivo em questão (nesse caso, J0388563.wav).

Nesse momento, as coisas ficam um pouco complicadas. Para começar, configuramos um loop For Next que é executado de 0 a 33; isso porque os arquivos são compatíveis com 31 propriedades estendidas diferentes que receberam números de índice de 0 a 3. (Observe que há alguns números, como 27 e 28, que são números de índice válidos mas não contêm valores de propriedades.) Na verdade, os arquivos são compatíveis com as propriedades mostradas na Figura 3.

Figure 3 Propriedades do arquivo

Índice Propriedade
0 Nome
1 Tamanho
2 Tipo
3 Data da modificação
4 Data da criação
5 Data de acesso
6 Atributos
7 Status
8 Proprietário
9 Autor
10 Título
11 Assunto
12 Categoria
13 Páginas
14 Comentários
15 Copyright
16 Artista
17 Título do álbum
18 Ano
19 Número do controle
20 Gênero
21 Duração
22 Taxa de bits
23 Protegido
24 Modelo da câmera
25 Data em que a imagem foi feita
26 Dimensões
29 Nome do episódio
30 Descrição do programa
32 Tamanho da amostra de áudio
33 Taxa da amostra de áudio

Então, o que fazemos dentro desse loop For Next? Bem, a primeira coisa é executar esta linha de código:

strHeader = _
  objFolder.GetDetailsOf(objFolder.Items, i)

O que estamos fazendo aqui é usar o método GetDetailsOf para recuperar o nome da propriedade 0 (lembre-se, o nosso loop é executado de 0 a 33). Então, armazenamos esse nome em uma variável nomeada strHeader e usamos essa linha de código para recuperar o valor de propriedade do item 0, armazenando as informações retornadas em uma variável nomeada strValue:

strValue = _
  objFolder.GetDetailsOf(objFolderItem, i)

Entendeu como funciona? O item 0 é a propriedade Name. Então, na primeira vez que o loop é percorrido, strHeader será igual a Name. Enquanto isso, o nome real (ou seja, o valor da propriedade Name) desse primeiro arquivo é J0388563.wav. Portanto, na primeira vez que o loop é percorrido, strValue será igual a J0388563.wav Quando o colocamos dessa forma, ele não parece tão complicado, não é mesmo?

Como você provavelmente já sabe, nem todos os tipos de arquivos são compatíveis com todas as propriedades estendidas. (Por exemplo, um arquivo .jpg não irá ter um título de álbum nem uma taxa de amostra de áudio.) Portanto, na próxima linha de código, verificamos para ver se um valor retornado é uma seqüência de caracteres vazia:

If strValue <> "" Then

Se o valor for uma seqüência de caracteres, então simplesmente voltamos para o início do loop e repetimos o processo com a próxima propriedade estendida. Se o valor não for uma seqüência de caracteres vazia, repetimos o nome da propriedade e o valor, da seguinte forma:

Wscript.Echo strHeader & vbTab & strValue

O resultado líquido? Algo muito semelhante a isso:

Nome    j0388563.wav
Tamanho    169 KB
Tipo    Wave Sound
Data de modificação   1/19/2004 8:56 AM
Data de criação    3/6/2006 2:02 PM
Data de acesso   12/3/2007 10:41 AM
Atributos      A
Status  Online
Proprietário   FABRIKAM\kenmyer
Taxa de bits        90kbps
Tamanho da amostra de áudio       4 bit
Taxa da amostra de áudio       11 kHz

Legal.

Estamos com pouco tempo (e espaço), mas se você procura uma forma mais fácil de retornar para os valores de propriedade mais relevantes, experimente o script na Figura 4.

Figure 4 Uma forma fácil de retornar valores de propriedade

Const colInfoTip = -1

Set objShell = CreateObject("Shell.Application")

Set objFolder = objShell.NameSpace("C:\Scripts")
Set objFolderItem = _
  objFolder.ParseName("01. Out On The Weekend (Album Version).wma)")

Wscript.Echo objFolder.GetDetailsOf(objFolderItem, colInfoTip)

O que esse script faz? Bem, se você estiver no Windows Explorer e parar o ponteiro do mouse sobre um arquivo, uma dica de ferramentas será exibida e lhe fornecerá algumas informações úteis sobre o arquivo, como as informações mostradas na Figura 5. Como você pode obter essas informações de dicas de ferramentas usando um script? É isso mesmo. Use o script que acabamos de mostrar:

Figura 5 Propriedades mostradas em uma dica de ferramentas

Figura 5** Propriedades mostradas em uma dica de ferramentas **

Artista: Neil Young
Título do álbum: Harvest
Ano: 1972
Número do controle: 1
Duração: 0:04:35
Tipo: Windows Media Audio file
Taxa de bits: 256kbps
Protegido: Yes
Tamanho: 5.31 MB 

Acabou o espaço que tínhamos para a coluna deste mês. Bem, uma última observação sobre pássaros. Um motivo para você estar atento aos pequenos pássaros é: em algumas partes do mundo, é considera-se má sorte um pássaro entrar na sua casa. Por quê? Porque isso significa que alguém que mora na casa irá morrer. (Em alguns casos isso é verdade somente se o pássaro pousar em um piano. Mas isso não é superstição, é apenas mistério.) Mas aqui está a parte interessante: em outras partes do mundo, um pássaro entrar na sua casa significa que alguém que mora lá irá se casar. Isso é que é estar preso entre a cruz e a espada, hein?

O desafio de script do Dr. Scripto

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

Março de 2008: script enigmático

O quebra-cabeça deste mês é um criptograma, o que significa que cada letra foi substituída por uma letra diferente. (Deixamos todos os símbolos e números intactos.) A mesma letra representará sempre uma letra substituída. Por exemplo, todas as ocorrências da letra a podem ser substituídas pela letra b, todas as ocorrências da letra b seriam substituídas pela letra z e assim por diante. Este é um exemplo simples:

tdsjqu dfoufs

é decodificado assim:

script center

A decodificação nesse caso foi feita substituindo cada letra pela letra do alfabeto que a precede; portanto, t foi substituído por s, d foi substituído por c e assim por diante.

O quebra-cabeça é um pouco mais aleatório do que isso. Decodifique esse script e você terá um script que abre uma instância do Microsoft Excel®, adiciona uma nova planilha, atribui quatro valores à primeira coluna na planilha e, em seguida, classifica essa coluna na ordem ascendente.

Divirta-se!

O quebra-cabeça

kqyjs edfjkzyrlyg = 1
kqyjs edyq = 2
kqyjs edjqtstqmj = 2

jzs quwzekzd = ktzfszquwzks("zekzd.faadlkfslqy")
quwzekzd.iljludz = stcz

jzs quwmqtxuqqx = quwzekzd.mqtxuqqxj.frr
jzs quwmqtxjozzs = quwmqtxuqqx.mqtxjozzsj(1)

quwmqtxjozzs.kzddj(1, 1) = "kfs"
quwmqtxjozzs.kzddj(1, 2) = "rqg"
quwmqtxjozzs.kzddj(1, 3) = "ufs"
quwmqtxjozzs.kzddj(1, 4) = "faz"

jzs quwtfygz = quwzekzd.fkslizkzdd.zysltztqm
quwtfygz.jqts quwtfygz, edfjkzyrlyg, , , , , , edyq, , , edjqtstqmj

ANSWER:

O desafio de script do Dr. Scripto

Resposta: script enigmático, março de 2008

Veja a chave para decodificar o script:

Actual Letter   a   b   c   d   e   f   g   h   i   j   k
Coded Letter    f   u   k   r   z   b   g   o   l   w   x

Actual Letter   l   m   n   o   p   q   r   s   t   u   v   w   x   y   z
Coded Letter    d   n   y   q   a   h   t   j   s   c   i   m   e   v   p

E aqui está o script decodificado:

Const xlAscending = 1
Const xlNo = 2
Const xlSortRows = 2

Set objExcel = CreateObject("Excel.Application")
objExcel.Visible = True

Set objWorkbook = objExcel.Workbooks.Add
Set objWorksheet = objWorkbook.Worksheets(1)

objWorksheet.Cells(1, 1) = "Cat"
objWorksheet.Cells(1, 2) = "Dog"
objWorksheet.Cells(1, 3) = "Bat"
objWorksheet.Cells(1, 4) = "Ape"

Set objRange = objExcel.ActiveCell.EntireRow
objRange.Sort objRange, xlAscending, , , , , , xlNo, , , xlSortRows

The Microsoft Scripting GuysA Equipe de Scripts trabalha na – quer dizer, é contratada pela – Microsoft. Quando não estão jogando/treinando/assistindo beisebol (e 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. A reprodução parcial ou completa sem autorização é proibida..