Hey, Scripting Guy!Spielen mit dem Shellobjekt

Die Scripting Guys von Microsoft

Laden Sie den Code für diesen Artikel herunter: HeyScriptingGuy2008_03.exe (150KB)

Dem alten Sprichwort zufolge kann kein Spatz zur Erde fallen, ohne dass der Himmel davon weiß. Die Scripting Guys wollen keineswegs dazu ermutigen, Spatzen vom Himmel zu holen. (Wenn sich allerdings jemand um diese lästigen Krähen auf dem Dach kümmern würde, die am Samstagmorgen um 7:00 Uhr zu lärmen anfangen, dann wäre das etwas anderes. [Der Skriptingredakteur mag Krähen. Wenn der Verfasser dieses Beitrags „sich um die Krähen kümmern“ sagt, meint er ganz bestimmt „dafür sorgen, dass es ihnen gut geht“. -d. Red.]) Dennoch ist es tröstlich zu wissen, dass immer jemand da ist, wenn wirklich etwas schief geht. Wie klein und bedeutungslos man auch erscheinen mag, irgendwo gibt es jemanden, der über einen wacht. [Selbst wenn es nur ein Redakteur ist. -d. Red.]

Was für Spatzen gilt, lässt sich auf die Skriptprogrammierung für die Systemadministration übertragen. In der Skriptingwelt dreht sich fast alles um die Schwergewichte des Skripting: Windows PowerShellTM, VBScript, WMI, ADSI und sogar FileSystemObject. Dass um diese Technologien der größte Rummel veranstaltet wird, ist nachvollziehbar. Schließlich lassen sich damit etliche interessante und nützliche Dinge anstellen. Das bedeutet jedoch nicht, dass dies die einzigen Technologien sind, die Skriptprogrammierern zur Verfügung stehen. Weit gefehlt.

Nehmen Sie zum Beispiel das Shellobjekt. Das Shellobjekt ist vielleicht weniger gut bekannt als Windows PowerShell, es ist jedoch wichtig und nach wie vor nützlich.

Es ist durchaus nicht abwegig, dass Sie früher oder später darum gebeten werden, ein Skript für die Systemadministration zu schreiben, das mit dem Shellobjekt arbeitet. Daraus ergibt sich zwangsläufig folgende Frage: Was genau lässt sich mit dem Shellobjekt anfangen? Wie sich herausstellt, können Sie mit dem Shellobjekt eine ganze Menge anfangen. Einige der Möglichkeiten (z. B. die Verwaltung von Datenträgerkontingenten und das Anzeigen einer Fortschrittsanzeige beim Kopieren oder Verschieben von Dateien) werden im Skriptinghandbuch für Microsoft® Windows® 2000 behandelt (microsoft.com/technet/scriptcenter/guide). Im Artikel dieses Monats zeigen wir Ihnen einige andere nützliche Dinge, für die das Shellobjekt verwendet werden kann und die Sie wahrscheinlich nie für möglich gehalten hätten – schon gar nicht mit dem Shellobjekt.

Ändern des Datums der letzten Änderung einer Datei

Viele von Ihnen denken wahrscheinlich beim Blick auf die vorhergehende Überschrift „Moment mal. Es ist nicht möglich, das Datum der letzten Änderung einer Datei mit einem Skript zu ändern, zumindest nicht mit VBScript.“ Darauf können wir nur erwidern: Wer hat Sie nur auf eine solche Idee gebracht?

Ach ja, stimmt: Vermutlich sind wir Scripting Guys dafür verantwortlich. Allerdings wissen wir nun, dass wir uns geirrt haben. Unglaublich! Es ist möglich, das Datum der letzten Änderung einer Datei mithilfe von VBScript zu ändern. Sie müssen lediglich das Shellobjekt verwenden.

Hinweis: Fragen Sie bitte nicht, wie die Scripting Guys sich in dieser Sache irren konnten. Nach all diesen Jahren sollte das ziemlich klar sein. Eine weitaus interessantere Frage ist diese: Wie in aller Welt bringen wir es je fertig, etwas richtig zu machen?

Sie möchten also das Datum der letzten Änderung einer Datei ändern? Dann verwenden Sie einfach dieses Skript:

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"

Wie Sie sehen, ist das nicht furchtbar kompliziert. Als Erstes erstellen Sie eine Instanz des Shell.Application-Objekts. (Verwechseln Sie aber Shell.Application nicht mit Wscript.Shell, dem Windows Script Host-Shellobjekt. Das Shellobjekt, mit dem Sie an dieser Stelle arbeiten, ist das Windows-Shellobjekt.) Nach dem Einrichten der Instanz des Shellobjekts stellen Sie mithilfe der Namespace-Methode eine Bindung an den Ordner „C:\Scripts“ her. Dann stellen Sie mithilfe der ParseName-Methode eine Bindung an eine angegebene Datei in diesem Ordner her. In diesem Fall stellen Sie eine Bindung an ein JPEG-Bild mit dem Dateinamen „Dr_Scripto.jpg“ her:

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

Welcher Schritt ist der nächste, nachdem Sie die Bindung an die Datei selbst hergestellt haben? Ganz einfach: Sie weisen der ModifyDate-Eigenschaft ein neues Datum und einen neuen Zeitpunkt zu:

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

Das wäre schon alles.

Wirklich. Das ist ziemlich beeindruckend, oder? Sobald Sie das Skript ausführen, wird das Datum der letzten Änderung für die Datei auf den 1. Januar 2008, 8:00 Uhr eingestellt. (Wenn Sie möchten, können Sie den Ordner „C:\Skripts“ in Windows-Explorer öffnen und sich selbst überzeugen.)

Mancher sagt sich jetzt vielleicht: „Interessant. Ich kann das Datum der letzten Änderung einer Datei ändern. Aber welchen Grund gibt es dafür, das Datum der letzten Änderung einer Datei zu ändern?“ Viele nutzen das Datum der letzten Änderung als eine Art Versionskontrollsystem. Wenn beispielsweise mehrere Kopien eines Skripts existieren, ist die Überprüfung des Datums der letzten Änderung eine Möglichkeit zum Nachverfolgen der offiziellen Version. Durch Überprüfen des Datums der letzten Änderung können Sie feststellen, ob es sich bei einer bestimmten Kopie des Skripts um eine unveränderte Version des ursprünglichen Skripts handelt.

Hinweis: Sicher, jemand könnte das soeben gezeigte Skript ausführen und das Datum der letzten Änderung ändern. Aber falls Sie nicht alles durch Codesignierung sichern, lässt sich immer eine Möglichkeit finden, das System zu überlisten. Vorausgesetzt, die Kollegen, mit denen Sie Skripts austauschen, haben ethische Grundsätze, ist diese Herangehensweise vernünftig.

Irgendwann entschließen Sie sich vielleicht dazu, das Datum der letzten Änderung für alle Skripts zu aktualisieren – und zu standardisieren. Wie erreichen Sie dies? Wenn sich alle Skripts im Ordner „C:\Scripts“ befinden, können Sie einfach den folgenden Codeabschnitt ausführen:

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

Wie Sie sehen, ähnelt der Anfang dieses Skripts dem des ersten Skripts, das hier aufgeführt wurde. In diesem Fall wird jedoch nach dem Binden an den Ordner „C:\Scripts“ nicht ParseName zum Binden an eine einzelne Datei in diesem Ordner verwendet. Stattdessen geben Sie mithilfe dieser Codezeile eine Auflistung aller in diesem Ordner enthaltenen Dateien zurück:

Set colItems = objFolder.Items

Wenn die Auflistung vorliegt, richten Sie eine „For Each“-Schleife ein, die alle Elemente in der Auflistung durchläuft. Innerhalb der „For Each“-Schleife ändern Sie mit der folgenden nützlichen Codezeile den Wert der ModifyDate-Eigenschaft der ersten Datei in der Auflistung in den 1. Januar 2008, 8:00 Uhr:

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

Dann wird die Schleife einfach erneut durchlaufen, und Sie wiederholen den Prozess mit der nächsten Datei in der Auflistung. Schließlich besitzen alle Dateien im Ordner „C:\Scripts“ (mit Ausnahme versteckter Dateien) dasselbe Datum der letzten Änderung. Sehen Sie, wie einfach das ist? Wer hat also behauptet, Sie können das Datum der letzten Änderung einer Datei nicht mit VBScript ändern?

Ach ja, richtig.

Da wir beim Thema irrige Annahmen sind ...

Vor Urzeiten, als die Scripting Guys gerade mit der Skriptprogrammierung für die Systemadministration begannen, gab es keine Möglichkeit zum Zugriff auf alle erweiterten Dateiinformationen, die im NTFS-Dateisystem mit einer Datei verknüpft sind. Wenn Sie beispielsweise mit der rechten Maustaste auf eine .wav-Datei und dann auf „Eigenschaften“ klicken, werden ähnliche Informationen angezeigt wie in Abbildung 1.

Abbildung 1 Zusammenfassung der Dateieigenschaften

Abbildung 1** Zusammenfassung der Dateieigenschaften **

Wie rufen Sie mithilfe eines Skripts Werte wie Bitrate oder Abtastgröße ab? Das ist nicht möglich. Es sei denn, Sie verwenden das Shellobjekt. (Oder Windows-Desktopsuche 3.0, wenn sie diese Software heruntergeladen und installiert haben.) An einem bestimmten Punkt erhielt das Shellobjekt die Fähigkeit, alle erweiterten Eigenschaftsinformationen für eine Datei abzurufen, die Scripting Guys haben dies jedoch übersehen. Daher haben wir immer behauptet: „Sie können die Bitrate einer .wav-Datei nicht mit einem Skript bestimmen“, obwohl dies tatsächlich möglich ist, wie der Code in Abbildung 2 zeigt.

Figure 2 Verwenden eines Skripts zum Ermitteln der Bitrate einer .wav-Datei

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

Wie genau funktioniert dieses Skript? Der Anfang gleicht dem des ersten Skripts, das Sie oben gesehen haben: Sie erstellen eine Instanz des Shell.Application-Objekts und eine Bindung an den Ordner „C:\Script“. Dann verwenden Sie die ParseName-Methode, um eine Bindung an die fragliche Datei zu erstellen (in diesem Fall J0388563.wav).

An diesem Punkt wird es ein wenig kompliziert. Zunächst richten Sie eine „For Next“-Schleife ein, die von 0 bis 33 ausgeführt wird, da Dateien bis zu 31 verschiedene erweiterte Eigenschaften mit den Indexnummern von 0 bis 33 unterstützen. (Beachten Sie, dass einige Nummern wie 27 und 28 zwar gültige Indexnummern sind, jedoch keine Eigenschaftswerte enthalten.) Die Dateien unterstützen die Eigenschaften, die in Abbildung 3 gezeigt werden.

Figure 3 Dateieigenschaften

Index Eigenschaft
0 Name
1 Größe
2 Typ
3 Änderungsdatum
4 Erstellungsdatum
5 Zugriffsdatum
6 Attribute
7 Status
8 Besitzer
9 Autor
10 Titel
11 Subjekt
12 Kategorie
13 Seiten
14 Bemerkungen
15 Copyright
16 Interpret
17 Albumtitel
18 Jahr
19 Titelnummer
20 Genre
21 Dauer
22 Bitrate
23 Geschützt
24 Kameramodell
25 Bild aufgenommen am
26 Abmessungen
29 Folgenname
30 Programmbeschreibung
32 Abtastgröße
33 Abtastrate

Was geschieht nun innerhalb der „For Next“-Schleife? Zunächst führen Sie die folgende Codezeile aus:

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

Sie verwenden hier die GetDetailsOf-Methode, um den Namen der Eigenschaft 0 abzurufen (die Schleife durchläuft die Nummern 0 bis 33). Dann speichern Sie diesen Namen in einer Variablen namens strHeader und rufen mithilfe der folgenden Codezeile den Eigenschaftswert des Elements 0 ab, wobei die zurückgegebenen Informationen in einer Variablen namens strValue gespeichert werden:

strValue = _
  objFolder.GetDetailsOf(objFolderItem, i)

Sehen Sie nun, wie dies funktioniert? Element 0 ist zufälligerweise die Name-Eigenschaft. Beim ersten Durchlaufen der Schleife ist also strHeader gleich Name. Der eigentliche Name (das heißt, der Wert der Name-Eigenschaft) der ersten Datei lautet J0388563.wav. Daher ist beim ersten Durchlaufen der Schleife strValue gleich J0388563.wav. So gesehen scheint das Ganze gar nicht so kompliziert, oder?

Sicher ist Ihnen bekannt, dass nicht alle Dateitypen alle erweiterten Eigenschaften unterstützen. (Eine .jpg-Datei hat beispielsweise keinen Albumtitel und keine Abtastrate.) In der nächsten Codezeile überprüfen Sie daher, ob ein zurückgegebener Wert eine leere Zeichenfolge ist:

If strValue <> "" Then

Wenn der Wert eine leere Zeichenfolge ist, springen Sie einfach zurück an den Anfang der Schleife und wiederholen den Prozess mit der nächsten erweiterten Eigenschaft. Ist der Wert keine leere Zeichenfolge, geben Sie den Eigenschaftsnamen und den Wert wie folgt zurück:

Wscript.Echo strHeader & vbTab & strValue

Das Ergebnis? Das sieht in etwa so aus:

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

Super.

Wir sind hier ein wenig in Zeit- und Platznot, wenn Sie jedoch nach einer noch einfacheren Möglichkeit suchen, die wichtigsten Eigenschaftswerte zurückzugeben, probieren Sie das Skript in Abbildung 4 aus.

Figure 4 Eine einfache Möglichkeit zur Rückgabe von Eigenschaftswerten

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)

Was bewirkt dieses Skript? Wenn Sie in Windows-Explorer mit dem Mauszeiger auf eine Datei zeigen, wird eine QuickInfo mit einigen nützlichen Informationen zur Datei angezeigt (siehe Abbildung 5). Wie können Sie diese QuickInfo-Informationen mithilfe eines Skripts abrufen? Richtig. Verwenden Sie das Skript, das wir Ihnen soeben gezeigt haben:

Abbildung 5 Anzeige von Eigenschaften in einer QuickInfo

Abbildung 5** Anzeige von Eigenschaften in einer QuickInfo **

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 

Das war schon alles für diesen Monat. Abgesehen von einer letzten Anmerkung zum Thema Spatzen. Es gibt einen guten Grund, warum Sie Spatzen nicht aus den Augen verlieren sollten: In manchen Regionen der Welt gilt es als schlechtes Omen, wenn ein Spatz in ein Haus fliegt. Warum? Weil es bedeutet, dass ein Hausbewohner sterben wird. (In einigen Fällen gilt dies nur, wenn sich der Spatz auf ein Klavier setzt. Aber das ist kein Aberglaube, sondern schlicht bizarr.) Interessant ist jedoch Folgendes: In anderen Teilen der Welt gilt ein Spatz im Haus als Zeichen dafür, dass ein Hausbewohner bald heiraten wird. Fragt sich worin der Fluch und worin der Segen liegt ...

Der Scripting Perplexer von Dr. Scripto

Die monatliche Herausforderung, die nicht nur Ihr Talent zum Rätsellösen testet, sondern auch Ihre Skriptingfähigkeiten.

März 2008: Rätselhaftes Skript

Das Rätsel dieses Monats ist ein Kryptogramm. Das heißt, jeder Buchstabe wurde durch einen anderen Buchstaben ersetzt. (Symbole und Zahlen wurden nicht verändert.) Ein Buchstabe wird immer durch denselben Buchstaben ersetzt. Beispiel: Alle Vorkommen des Buchstabens a könnten durch den Buchstaben b ersetzt worden sein, alle Vorkommen des Buchstabens b durch z, und so weiter. Hier ein einfaches Beispiel:

tdsjqu dfoufs

lässt sich wie folgt entschlüsseln:

script center

Die Entschlüsselung erfolgte in diesem Fall durch Ersetzen jedes Buchstabens durch den jeweils vorausgehenden Buchstaben im Alphabet. Das heißt, t wurde durch s ersetzt, d durch c, und so weiter.

Im Rätsel spielt der Zufall eine etwas größere Rolle. Durch Entschlüsseln dieses Skripts erhalten Sie ein Skript, das eine Instanz von Microsoft Excel® öffnet, eine neue Tabelle hinzufügt, der ersten Spalte in der Tabelle vier Werte zuordnet und diese Spalte dann in aufsteigender Reihenfolge sortiert.

Viel Spaß!

Das Rätsel

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:

Der Scripting Perplexer von Dr. Scripto

Antwort: Rätselhaftes Skript, März 2008

Hier ist der Schlüssel zum Decodieren des Skripts:

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

Und hier ist das eigentliche decodierte Skript:

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

Die Scripting Guys von MicrosoftDie Scripting Guys von Microsoft arbeiten für Microsoft (oder sind zumindest dort angestellt). Wenn sie nicht gerade ihrem Hobby, dem Baseball (oder verschiedenen anderen Aktivitäten) nachgehen, betreiben sie das TechNet-Skriptcenter. Besuchen Sie es unter www.scriptingguys.com.

© 2008 Microsoft Corporation und CMP Media, LLC. Alle Rechte vorbehalten. Die nicht genehmigte teilweise oder vollständige Vervielfältigung ist nicht zulässig.