Umgebungsvariablen und Eingabedateien in Skripts

10.02.2007 von Martin Kuppinger
In den meisten Fällen sollen Skripts nicht immer in der gleichen Form arbeiten, sondern über Parameter gesteuert werden. Dafür gibt es neben Dialogfeldern zwei probate Mittel. Zum einen können Umgebungsvariablen verwendet werden, zum anderen Eingabedateien. Der Artikel erläutert die Nutzung bei VBscript.

Die meisten der bisher vorgestellten Skripts haben eine relativ statische Struktur und arbeiten nicht oder kaum mit Eingaben. In vielen Fällen geht es aber darum, ähnliche Aufgaben mit Hilfe von Skripts zu automatisieren, und nicht identische Aufgaben. Entsprechend werden Parameter benötigt, die das Verhalten der Skripts steuern. Dafür findet man verschiedene Ansätze:

In diesem Artikel wird zunächst auf das Einlesen von Umgebungsvariablen eingegangen, den einfachsten Ansatz bezüglich der Programmierung von Skripts. Außerdem wird die Verwendung einer Textdatei als Datenquelle und die Verarbeitung von Parametern beim Aufruf besprochen. Die Verwendung von Excel als Quelle werden wir im dritten Teil der Serie „Active Directory-Scripting“ an einem Beispiel erläutern.

Bild 1: Die Ausgabe von Umgebungsvariablen mit einem Skript.

Umgebungsvariablen und WshShell


Umgebungsvariablen sind ein Mechanismus, den man schon seit DOS-Zeiten kennt. Diese Variablen lassen sich einfach anpassen. Über die Systemsteuerung können sowohl Benutzer- als auch Systemvariablen erstellt und angepasst werden. Neben den Standardvariablen können auch eigene Variablen erstellt werden, um zusätzliche Aufgaben durchzuführen – also beispielsweise für die Parametrisierung von Skripts.

Der einfachste Ansatz für die Nutzung von Umgebungsvariablen ist der Zugriff auf die Eigenschaft Environment des WshShell-Objekts. Das Shell-Objekt liefert den Zugriff auf die Ausführungsumgebung, also die Windows-Shell. Es wird auch für die Bearbeitung der Registry und von Desktop-Einstellungen verwendet.

Über diese Eigenschaft können alle Umgebungsvariablen gelesen werden. Dabei werden verschiedene Typen unterschieden:

In der Regel werden die ersten beiden Typen genutzt, wobei die meisten Umgebungsvariablen für das System definiert sind. Dort gibt es viele vordefinierte Variablen, mit denen sich beispielsweise das Betriebssystem und dessen Version, der Prozessor oder das Windows-Systemverzeichnis ermitteln lassen. Diese Informationen können in Skripts eingesetzt werden, wenn beispielsweise bestimmte Codeteile nur mit bestimmten Betriebssystemversionen genutzt werden können.

Listing 1: Der Zugriff auf Umgebungsvariablen
Set WshShell = WScript.CreateObject("WScript.Shell")
Set WshEnvSys = WshShell.Environment("SYSTEM")
Set WshEnvUsr = WshShell.Environment("USER")
WScript.Echo "Anzahl der Prozessoren: " & WshEnvSys("NUMBER_OF_PROCESSORS")
WScript.Echo "Temporäre Dateien des Benutzers: " & WshEnvUsr("TEMP")


Mit der ersten Anweisung aus Listing 1 wird ein Objekt der Klasse WshShell erzeugt. Damit kann auf die Arbeitsumgebung zugegriffen werden. Über die beiden folgenden Anweisungen wird die Eigenschaft Environment ausgelesen, und zwar einmal für das System und einmal für den Benutzer. Anschließend werden die Werte von jeweils einer Variablen ausgegeben.

Alternativ dazu könnten die Informationen auch in weitere Variablen geschrieben und beispielsweise bei Bedingungen verwendet werden. Dazu würde eine Anweisung in der Form

tmpDir = WshEnvUsr("TEMP")

verwendet werden. Das Konzept ist relativ einfach und daher schnell umsetzbar, hat aber den Nachteil, dass die Umgebungsvariablen jeweils über die Systemsteuerung angepasst werden müssen.

Umgebungsvariablen und WMI

Diese Problematik wird auch bei Verwendung von WMI für den Zugriff auf die Umgebungsvariablen nicht gelöst. Listing 2 zeigt ein Beispiel für ein Skript, das über WMI arbeitet.

Listing 2: Das Auslesen von Umgebungsvariablen mit WMI
(Quelle: Microsoft)
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colVar = objWMIService.ExecQuery( _
"Select * from Win32_Environment")
For Each objVar in colVar
Wscript.Echo "Description: " & objVar.Description _
& VBNewLine & "Name: " & objVar.Name _
& VBNewLine & "System Variable: " _
& objVar.SystemVariable & VBNewLine _
& "User Name: " & objVar.UserName & VBNewLine _
& "Variable Value: " & objVar.VariableValue
Nex

In diesem Fall wird auf die Klasse Win32_Environment zugegriffen. Der Rückgabewert ist eine Collection der verschiedenen Umgebungsvariablen. Für diese werden sehr viele Eigenschaften geliefert, die ausgelesen werden können. Damit stehen entsprechend mehr Optionen für die Verarbeitung der Umgebungsvariablen zur Verfügung. So kann beispielsweise auch der Besitzer einer Umgebungsvariablen ermittelt werden. Bild 2 zeigt die Ausgabe der Informationen.

Bild 2: Die über WMI ausgelesenen Umgebungsvariablen.

Um nicht alle Variablen auszugeben, muss bei der Verarbeitung mit Abfragen gearbeitet werden. Diese können in die Schleifenbedingung oder anschließend als If-End-If-Anweisungen integriert werden.

Textdateien als Datenquelle

Eine Option ist die Verwendung von Textdateien für die Eingabe. In solchen Dateien können beispielsweise auch lange Listen von Computern aufgeführt werden. Listing 3 zeigt ein Beispiel für eine solche (einfache) Eingabedatei.

Listing 3: Eine Eingabedatei mit Servernamen
windowstest1
windowstest2
windowstest3


Diese Datei lässt sich relativ einfach verarbeiten, vor allem weil es sich um nur eine Art von Informationen handelt und daher beim Einlesen keine komplexere Analyse erforderlich ist.

Das Beispiel zeigt eine Variante, die als Grundgerüst für eigene Skripts in diesem Bereich bestens geeignet ist. Zunächst wird eine Konstante definiert, die später beim Öffnen der Datei verwendet wird und festlegt, dass sie nur zum Lesen geöffnet wird.

Anschließend wird ein Dictionary-Objekt erzeugt. Diese Objektklasse wird für Aufzählungen verwendet und kann wie ein Array genutzt werden. Außerdem muss ein Objekt für den Zugriff auf das Dateisystem erstellt werden. Mit diesem wird nun eine Textdatei zum Lesen geöffnet, wobei der Name der Datei in diesem Fall fest kodiert ist. Er könnte beispielsweise über einen Parameter beim Aufruf angegeben werden.

Listing 4: Skript zur Verarbeitung der Liste von Servern
(Quelle: Microsoft)
Const ForReading = 1
Set objDictionary = CreateObject("Scripting.Dictionary")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile _
("c:\skripts\servers.txt", ForReading)
i = 0
Do Until objTextFile.AtEndOfStream
strNextLine = objTextFile.Readline
objDictionary.Add i, strNextLine
i = i + 1
Loop
For Each objItem in objDictionary
StrComputer = objDictionary.Item(objItem)
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer& "\root\cimv2")
Set colServices = objWMIService.ExecQuery _
("SELECT * FROM Win32_Service")
Wscript.Echo strComputer, colServices.Count
Next

Die Datei wird nun zeilenweise ausgelesen, wobei als Endebedingung für die Schleife die Eigenschaft AtEndOfStreamdes Dateisystemobjekts verwendet wird. Für die Navigation wird die Methode ReadLine verwendet, die automatisch von Zeile zu Zeile springt. Nach dem Einlesen einer Zeile wird diese in das Dictionary-Objekt geschrieben. Die Verarbeitung erfolgt über die zweite Schleife. Innerhalb dieser Schleife wird für jedes Element in dem Dictionary-Objekt jeweils die Anzahl der Dienste ermittelt und ausgegeben (Bild 3).

Bild 3: Die Ausgabe der Anzahl an Diensten auf den Servern.

Dieses Skript lässt sich nun noch „verfeinern“, um beispielsweise Dateien mit der klassischen .ini-Struktur einzulesen, bei der es Abschnitte und innerhalb der Abschnitte Parameter gibt. Dazu können beispielsweise mehrere Dictionary- Objekte für die verschiedenen Abschnitte genutzt werden, aber auch Arrays. Beim Einlesen muss analysiert werden, ob in der Textdatei ein neuer Abschnitt definiert wird und ob es sich um einen Eintrag handelt oder um eine Leerzeile. Ein Beispiel für ein solches Skript wird in einer der folgenden Ausgaben von Expert’s inside Windows NT/2000 vorgestellt.

Parameter einlesen

Eine weitere Option ist die Verwendung von Parametern, die beim Aufruf an der Befehlszeile angegeben
werden. Insgesamt ist das vielleicht der einfachste Ansatz (Listing 5).

Listing 5: Das Einlesen von Argumenten an der Befehlszeile
Set args = WScript.Arguments
For i=0 To args.count-1
StrComputer = args(i)
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer& "\root\cimv2")
Set colServices = objWMIService.ExecQuery _
("SELECT * FROM Win32_Service")
Wscript.Echo strComputer, colServices.Count
Next

In diesem Fall kommt die Klasse WshArguments zum Einsatz. Durch das Setzen der Variablen in der ersten Zeile des Skripts werden die Aufrufparameter der Variablen args zugewiesen, sie müssen nun nur noch verarbeitet werden. In diesem Fall wird eine Schleife verwendet. Da die Nummerierung bei 0 beginnt, muss die Schleife von 0 bis zu einem Wert laufen, der um 1 kleiner ist als die Anzahl der Elemente. Bei drei Elementen haben diese beispielsweise die Indizes 0 bis 2. In der Schleife erfolgt die Verarbeitung exakt wie in Listing 4. Auch die Ausgabe ist gleich – der einzige Unterschied ist, dass nun Befehlszeilenparameter
übergeben werden müssen.

Bild 4: Die Verwendung von Befehlszeilenparametern.

Auch hier lässt sich noch mehr machen. So könnten beispielsweise Parameter in der Art von

/s:windowstest1

verwendet werden. In diesem Fall müsste die Verarbeitung so gestaltet werden, dass der Parameter identifiziert und der Wert anschließend in eine Variable geschrieben wird.

Die verschiedenen Beispiele zeigen, dass es relativ einfach ist, externe Eingaben in Skripts zu verarbeiten und diese damit über Parameter zu steuern. Alle Listings in diesem Artikel können als Raster für eigene Lösungen dienen, weil sie jeweils die Grundstruktur der Verarbeitung illustrieren.