Hey, Scripting Guy!I giochi di Shell preferiti

Microsoft Scripting Guys

Scarica il codice per questo articolo: HeyScriptingGuy2008_03.exe (150KB)

Come dice il vecchio proverbio: anche il passero più piccolo non può cadere in terra all'insaputa del cielo. Ora, ciò che gli Scripting Guy suggeriscono non è che la gente va in giro a colpire i passeri che volano nel cielo. Anche se qualcuno volesse prendersi cura di quegli stupidi corvi che ogni sabato mattina alle 7:00 si siedono sul tetto e stridono, questa è tutta un'altra storia. [L'editor di script ama i corvi, dunque siamo sicuri che l'espressione "prendersi cura di" utilizzata dagli Scripting Guy in questo articolo significa "accertarsi che essi siano al sicuro". -Ed.] Tuttavia, è confortante sapere che c'è sempre qualcuno che si preoccupa di te, non importa quanto tu sia piccolo o insignificante, c'è sempre qualcuno che ti sorveglia. [Anche se quel qualcuno è solo un editor. -Ed.]

Ciò che è vero per i passerotti vale anche per gli script per l'amministrazione del sistema. Si può dedurre che, nel mondo degli script, l'attenzione viene focalizzata principalmente sul kahunas di script di grandi dimensioni: Windows PowerShellTM, VBScript, WMI, ADSI, persino FileSystemObject. È comprensibile che queste tecnologie siano fortemente pubblicizzate; dopo tutto consentono di fare molte cose veramente eccellenti e utili. Ciò non significa, però, che queste siano le sole tecnologie disponibili per gli autori di script. Lungi da noi affermare una cosa del genere.

Si pensi ad esempio all'oggetto Shell. Nonostante l'oggetto Shell potrebbe non essere altrettanto noto o ampiamente pubblicizzato quanto Windows PowerShell, è comunque importante e utile.

Molto probabilmente qualcuno, prima o poi, chiederà di scrivere uno script per l'amministrazione del sistema che utilizzi l'oggetto Shell. Ciò porta a una domanda ovvia: cosa si può fare esattamente con l'oggetto Shell? Ebbene, ci sono tante cose interessanti che è possibile fare con l'oggetto Shell, alcune delle quali (come la gestione delle quote disco e la visualizzazione di un indicatore di stato durante la copia o lo spostamento dei file) sono state trattate nella Guida sugli script di Microsoft® Windows® 2000, (microsoft.com/technet/scriptcenter/guide). Nell'articolo di questo mese, verranno illustrate altre piccole ingegnosità, cose che non si pensava affatto fosse possibile fare, tantomeno tramite l'oggetto Shell.

Modifica della data dell'ultima modifica di un file

Probabilmente molti di voi leggendo questo titolo stanno pensando: "Hey, aspetta un secondo. Non è possibile modificare la data dell'ultima modifica di un file utilizzando uno script, o perlomeno non utilizzando VBScript". A queste persone possiamo dire una sola cosa: hai mai sentito parlare di un'idea del genere?

Beh, in effetti, noi Scripting Guy abbiamo probabilmente affermato qualcosa del genere in passato, vero? Ebbene, ci sbagliavamo. Sconvolgente, vero? È possibile modificare la data dell'ultima modifica di un file utilizzando VBScript. Occorre semplicemente utilizzare l'oggetto Shell.

Nota: non preoccuparti di chiedere in che modo gli Scripting Guy abbiano potuto sbagliarsi; dopo tutti questi anni, dovrebbe essere piuttosto ovvio. Ecco una domanda molto più interessante: quando siamo riusciti a fare qualcosa di giusto?

Dunque, vuoi modificare la data dell'ultima modifica di un file, eh? Utilizza questo 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"

Come puoi vedere, non c'è nulla di così terribilmente complicato. Iniziamo creando un'istanza dell'oggetto Shell.Application. Attenti a non confondere Shell.Application con Wscript.Shell, l'oggetto Shell di Windows Script Host. L'oggetto Shell che utilizziamo oggi è l'oggetto Shell di Windows. Dopo aver attivato l'istanza dell'oggetto Shell, utilizziamo il metodo Namespace per creare un'associazione alla cartella C:\Scripts, quindi utilizziamo il metodo ParseName, dal nome bizzarro, per creare un'associazione a un file specifico all'interno di quella cartella. In questo caso, stiamo collegando un'immagine JPEG al nome file Dr_Scripto.jpg:

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

Dopo aver creato un'associazione al file stesso, cosa facciamo? La risposta è semplice; assegniamo semplicemente una nuova data e una nuova ora alla proprietà ModifyDate:

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

Ecco fatto.

L'operazione è riuscita. Molto interessante, vero? Una volta eseguito lo script, la data dell'ultima modifica del file verrà impostata su 01 gennaio 2008, ore 8:00. Per fare una verifica, è possibile aprire la cartella C:\Scripts di Windows Explorer.

Naturalmente, alcuni di voi staranno pensando, "Grande! Posso modificare la data dell'ultima modifica di un file. Ma per quale motivo al mondo dovrei voler modificare la data dell'ultima modifica di un file?" In molti casi gli utenti utilizzano la data dell'ultima modifica come una specie di sistema di controllo della versione; se, ad esempio, ci sono più copie di uno script in circolazione, un modo per tenere traccia della versione ufficiale è verificare la data dell'ultima modifica. Controllando la data dell'ultima modifica è possibile stabilire se una determinata copia di script è una versione modificata o meno dello script originale.

Nota: è vero che qualcuno può eseguire lo script appena illustrato e modificare la data dell'ultima modifica, ma oltre alla firma del codice, qualcuno potrebbe addirittura trovare un modo per colpire il sistema. Se i propri script sono condivisi con alcuni colleghi dotati di una certa etica, questo approccio risulta ragionevole.

A un certo punto potresti decidere di voler aggiornare e standardizzare la data dell'ultima modifica per tutti i tuoi script. Come puoi fare? Supponendo che tutti gli script si trovino nella cartella C:\Scripts, è possibile eseguire semplicemente il seguente frammento di codice:

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

Come puoi notare, questo script inizia in un modo molto simile al primo script illustrato. Tuttavia, in questo caso, dopo aver creato un'associazione alla cartella C:\Scripts, non utilizziamo ParseName per creare un'associazione a un singolo file all'interno di quella stessa cartella. Utilizziamo, invece, questa riga di codice per restituire una raccolta di tutti i file trovati in quella cartella:

Set colItems = objFolder.Items

Una volta ottenuta la nostra raccolta, impostiamo un ciclo For Each per eseguire tutti gli elementi nella raccolta. All'interno del ciclo For Each, utilizziamo questa utile riga di codice per modificare il valore della proprietà ModifyDate del primo file nella raccolta con 01 gennaio 2008, 8:00:

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

Il ciclo prosegue e il processo viene ripetuto con il file successivo della raccolta. Al termine di questo ciclo, tutti i file presenti nella cartella C:\Scripts (ad eccezione dei file nascosti) avranno la stessa data dell'ultima modifica. Visto quanto è facile? Chi ha detto che non è possibile modificare la data dell'ultima modifica di un file mediante VBScript?

Ok, lasciamo perdere.

A proposito di errori...

Tanto tempo fa, quando gli Scripting Guy hanno iniziato a utilizzare per la prima volta gli script per l'amministrazione dei sistemi, non era possibile accedere in alcun modo a tutte le informazioni sul file che venivano allegate a un file nel file system NTFS. Ad esempio, se fai clic con il pulsante destro del mouse su un file wav e poi su Proprietà, vengono visualizzate informazioni simili a quelle presenti nella Figura 1.

Figura 1 Riepilogo delle proprietà del file

Figura 1** Riepilogo delle proprietà del file **

In che modo è possibile recuperare valori come Velocità in bit o Dimensioni campione audio mediante uno script? Non è possibile, a meno che non utilizzi l'oggetto Shell. Oppure Windows Desktop Search 3.0, dando per scontato che tale software sia stato scaricato e installato. La possibilità di recuperare tutte le informazioni sulla proprietà di un file è stata aggiunta all'oggetto Shell, ma gli Scripting Guy hanno trascurato questo aspetto. Di conseguenza, continuano a dire che non è possibile utilizzare uno script per stabilire la velocità in bit di un file wav, anche se, come dimostrato dal codice nella Figura 2, è di fatto possibile.

Figure 2 Utilizzare uno script per individuare la velocità in bit di un file 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

Come funziona lo script? Anche questo script inizia allo stesso modo del primo, già illustrato in precedenza: si crea un'istanza dell'oggetto Shell.Application e un'associazione alla cartella C:\Scripts, successivamente si utilizza il metodo ParseName per creare un'associazione al file in questione (in questo caso, J0388563.wav).

A questo punto, le cose diventano un po' più complicate. Per iniziare, viene impostato un ciclo For Next che viene eseguito da 0 a 33 volte; ciò avviene perché i file supportano altrettante 31 proprietà estese differenti a cui sono stati associati numeri di indice da 0 a 33. (Tenere presente che ci sono alcuni numeri, come 27 e 28, che sono numeri di indice validi ma non contengono alcun valore della proprietà). Infatti, i file supportano le proprietà illustrate nella Figura 3.

Figure 3 Proprietà del file

Indice Proprietà
0 Nome
1 Dimensione
2 Tipo
3 Data di modifica
4 Data di creazione
5 Data di accesso
6 Attributi
7 Stato
8 Proprietario
9 Autore
10 Titolo
11 Oggetto
12 Categoria
13 Pagine
14 Commenti
15 Copyright
16 Artista
17 Titolo album
18 Anno
19 Numero del brano
20 Genere
21 Durata
22 Velocità in bit
23 Protetto
24 Modello di macchina fotografica
25 Data della foto
26 Dimensioni
29 Nome episodio
30 Descrizione programma
32 Dimensioni campione audio
33 Frequenza campionamento audio

Che cosa viene eseguito all'interno del ciclo For Next? Per prima cosa viene eseguita la riga di codice riportata di seguito:

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

Si tratta di utilizzare il metodo GetDetailsOf per richiamare il nome della proprietà 0 (non dimenticare che il ciclo viene eseguito da 0 a 33 volte). Tale nome viene poi memorizzato in una variabile definita strHeader e questa riga di codice viene utilizzata per recuperare il valore della proprietà dell'elemento 0, archiviando le informazioni restituite in una variabile definita strValue:

strValue = _
  objFolder.GetDetailsOf(objFolderItem, i)

Visto come funziona? L'elemento 0 è il nome della proprietà Name. Alla prima esecuzione del ciclo, strHeader conterrà lo stesso valore di Name. Nel frattempo, il nome reale (ossia, il valore della proprietà Name) per il primo file è J0388563.wav. Pertanto, alla prima esecuzione del ciclo, strValue conterrà lo stesso valore di J0388563.wav. Posto in questo modo, non sembra così complicato, vero?

Come forse si saprà, non tutti i tipi di file supportano tutte le proprietà estese. Ad esempio, un file jpg non disporrà di un valore tipo Titolo album o Frequenza campionamento audio. Pertanto, nella prossima riga di codice, si verifica se un valore restituito è una stringa vuota:

If strValue <> "" Then

Se il valore è una stringa vuota, occorre semplicemente tornare all'inizio del ciclo e ripetere il processo con la successiva proprietà estesa. Se il valore non è una stringa vuota, vengono restituiti il nome e il valore della proprietà, come illustrato di seguito:

Wscript.Echo strHeader & vbTab & strValue

Il risultato finale? Qualcosa molto simile a quanto segue:

Name    j0388563.wav
Size    169 KB
Type    Wave Sound
Date Modified   1/19/2004 8:56 AM
Date Created    3/6/2006 2:02 PM
Date Accessed   12/3/2007 10:41 AM
Attributes      A
Status  Online
Owner   FABRIKAM\kenmyer
Bit Rate        90kbps
Audio Sample Size       4 bit
Audio Sample Rate       11 kHz

Bene.

Il tempo e lo spazio a nostra disposizione per l'esecuzione è breve, ma se si è alla ricerca di un metodo ancora più semplice per restituire i valori delle proprietà più importanti, provare con lo script della Figura 4.

Figure 4 Un modo semplice per restituire i valori della proprietà

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)

Cosa fa questo script? Se si utilizza Windows Explorer e con il puntatore del mouse ci si sofferma su un file, viene visualizzata una descrizione comando contenente informazioni utili sul file, come quelle illustrate nella Figura 5. Come è possibile ottenere tali informazioni della descrizione comando utilizzando uno script? Proprio così. Utilizzare lo script appena illustrato:

Figura 5 Proprietà illustrate in una descrizione comando

Figura 5** Proprietà illustrate in una descrizione comando **

Artist: Neil Young
Album Title: Harvest
Year: 1972
Track Number: 1
Duration: 0:04:35
Type: Windows Media Audio file
Bit Rate: 256kbps
Protected: Yes
Size: 5.31 MB 

Questo è tutto per questo mese. Ancora un ultimo appunto sui passerotti. Ecco un motivo valido per tenere traccia dei piccoli passeri: in alcune parti del mondo, c'è una credenza secondo la quale un passero che entra nella propria casa è indice di malaugurio. Perché? Significa che uno degli abitanti di quella casa sta per morire. In alcuni casi tale credenza è vera solo se il passero atterra su un pianoforte. Ma non si tratta di una superstizione, è più che altro qualcosa di misterioso. Ma ecco la parte davvero interessante: in altre parti del mondo, se un passero entra in casa significa che uno dei membri di quella famiglia si sposerà a breve. Come trovarsi tra l'incudine e il martello, vero?

Il rompicapo di script del Dottor Scripto.

La sfida mensile che verifica non solo le tue capacità di risoluzione degli enigmi, ma anche le tue competenze di scripting.

Marzo 2008: Script enigmatico

L'enigma di questo mese è un crittogramma, vale a dire che ogni lettera è stata sostituita da una lettera diversa. Tutti i simboli e i numeri sono stati lasciati intatti. La stessa lettera rappresenterà sempre una lettera sostituita. Ad esempio, tutte le occorrenze della lettera a potrebbero essere sostituite dalla lettera b, tutte le occorrenze della lettera b verrebbero sostituite dalla z e così via. Ecco un semplice esempio:

tdsjqu dfoufs

prova a decodificare quanto segue:

script center

La decodifica in questo caso è stata eseguita sostituendo ogni lettera dell'alfabeto con quella che la precede, così la t è stata sostituita dalla s, la d dalla c, e così via.

L'enigma non è proprio così lineare. Se si decodifica questo script si ottiene uno script che apre un'istanza di Microsoft Excel®, aggiunge un nuovo foglio di calcolo, assegna quattro valori alla prima colonna del foglio di calcolo e ordina tale colonna in modo crescente.

Buon divertimento.

L'enigma

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:

Il rompicapo di script del Dottor Scripto.

Risposta: Script enigmatico, marzo 2008

Ecco la chiave per decodificare lo 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

Mentre questo è lo script effettivamente decodificato:

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

Microsoft Scripting GuysGli Scripting Guy lavorano per Microsoft, o meglio... sono dipendenti Microsoft. Quando non si dedicano al baseball (o a varie altre attività) da giocatori, allenatori o semplici spettatori, gestiscono il TechNet Script Center. Consultare la pagina www.scriptingguys.com.

© 2008 Microsoft Corporation e CMP Media, LLC. Tutti i diritti riservati. È vietata la riproduzione completa o parziale senza autorizzazione.