WMI-Scripting

09.02.2007 von Martin Kuppinger
Im abschließenden Teil der Artikelserie liegt der Schwerpunkt beim Zugriff auf Informationen über Softwarekomponenten und Treiber und den entsprechenden Funktionen bei WQL. Aber auch ergänzende Aspekte der Verwendung von WMI beim Scripting werden näher betrachtet.

Nachdem in den ersten beiden Teilen der Serie Grundlagen des WMI-Scriptings und der Umgang mit Hardwareressourcen erläutert wurden, geht es in dieser Folge vor allem um Methoden und Eigenschaften von Softwarekomponenten wie Diensten und Treibern. WMI stellt auch hier umfassende Funktionen zur Verfügung. Außerdem werden noch einige Details erläutert, unter anderem zum Verbindungsaufbau und zur WMI Scripting Library.

Das Beispiel Computerverwaltung

Auch wenn die Computerverwaltung nicht auf Basis von Skripts arbeitet, ist sie doch ein gutes Beispiel für die Möglichkeiten, die WMI bietet – zumindest bei Windows 2000. Dort findet sich noch der Bereich Systeminformationen, in dem Informationen über das System angezeigt werden (Bild 1). Er nutzt WMI, um diese Informationen zu sammeln. Zu den angezeigten Informationen gehören auch detaillierte Daten zur
Softwareumgebung mit den Treibern, Diensten und vielen weiteren Informationen.

Bild 1: In der Computerverwaltung von Windows 2000 werden über WMI viele Systeminformationen ermittelt.

Solche Informationen lassen sich entsprechend auch über Skripts abfragen, da beim Scripting auf die gleichen Methoden und Eigenschaften zugegriffen werden kann. Entsprechend lassen sich mit vergleichsweise einfachen WMI-Skripts recht umfassende Anwendungen realisieren.

Auf solche Skripts, mit denen beispielsweise auf Dienste, Konfigurationsinformationen des Systems und andere Informationen zugegriffen werden kann, wird nachfolgend eingegangen.

Überblick über die Dienste

Ein erstes einfaches Beispiel findet sich in Listing 1. Mit dem Skript werden die laufenden Dienste abgefragt, in diesem Fall auf dem lokalen System.

strComputer = "."
Set wbemServices = GetObject("winmgmts:\\" & strComputer)
Set wbemObjectSet = wbemServices.InstancesOf("Win32_Service")
For Each wbemObject In wbemObjectSet
WScript.Echo "Anzeigename: " & wbemObject.DisplayName & vbCrLf & _
" Status: " & wbemObject.State & vbCrLf & _
" Startart: " & wbemObject.StartMode
Next

Bild 2: Die Ausgabe des Skripts aus Listing 1.

Das Skript ist wie meist sehr einfach. Es wird auf das lokale System zugegriffen, um dort die Instanzen von Win32_Service zu ermitteln, also eine Liste der Dienste auszugeben. Für jeden Dienst werden drei Informationen abgefragt:

Das Skript sollte in jedem Fall mit

cscript skriptname.vbs

aufgerufen werden. Da es sehr viele Dienste gibt, führt die Verwendung von wscript.exe dazu, dass entsprechend viele einzelne Fenster mit Dienstinformationen eingeblendet werden. Natürlich lässt sich das Skript auch eleganter gestalten, indem man beispielsweise einen mehrzeiligen Ausgabetext generiert, wie es in Heft 10/2005 von Expert’s inside Windows NT/2000 an mehreren Beispielen illustriert wurde.

Mit dem einfachen Auflisten sind die Möglichkeiten aber noch lange nicht ausgeschöpft, wie ein Blick auf die Methoden der Klasse Win32_Service zeigt. Die Methoden und Eigenschaften aller Klassen sind unter

http://msdn.microsoft.com/library/en-us/wmidsk/wmi

dokumentiert. Zu den Methoden gehören unter anderem

Gerade das Löschen von Diensten ist von Interesse, weil man gelegentlich bei der Administration vor der Situation steht, dass beim Deinstallieren von Anwendungen nicht alle Dienste korrekt entfernt wurden. Man kann diese nun zwar deaktivieren, sie finden sich aber weiterhin in der Liste der Dienste. Die Methode Delete erlaubt dagegen auch das Entfernen von Diensten aus der Dienstliste. Für die Methode sind umfangreiche Statuscodes definiert, die zurückgeliefert werden. Damit lässt sich innerhalb von Skripts einfach ermitteln, ob der Dienst gelöscht werden konnte und, falls nicht, was die Ursache dafür war.

Neben den verschiedenen Methoden gibt es auch etliche Eigenschaften, die bei Diensten abgefragt werden können. Alle Eigenschaften haben den Zugriffstyp Read-Only, können also nicht verändert werden. Teilweise findet man aber Methoden, mit denen sich Änderungen vornehmen lassen. Dazu zählen die genannte Methode ChangeStartMode und die Methode Change für allgemeine Änderungen an der Konfiguration von Diensten.

Mit den Methoden und Eigenschaften lassen sich beispielsweise Skripts entwickeln, mit denen überprüft wird, ob ein bestimmter Dienst installiert ist. Die Startart kann anschließend auf den gewünschten Wert angepasst werden.

Betriebssysteminformationen

Über WMI können auch Statusinformationenn des Betriebssystems ermittelt werden. Das Listing 2 zeigt ein Beispiel für ein Skript, das solche Informationen ausliest und anzeigt.

Listing 2: Skript für den Zugriff auf wichtige Einstellungen des
Betriebssystems
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer)
Set colOperatingSystems = objWMIService.InstancesOf("Win32_OperatingSystem")
For Each objOperatingSystem In colOperatingSystems
Wscript.Echo "Name: " & objOperatingSystem.Name & vbCrLf & _
"Bezeichnung: " & objOperatingSystem.Caption & vbCrLf & _
"Aktuelle Zeitzone: " & objOperatingSystem.CurrentTimeZone & vbCrLf & _
"Letzte Startzeit: " & objOperatingSystem.LastBootUpTime & vbCrLf & _
"Lokale Zeit: " & objOperatingSystem.LocalDateTime & vbCrLf & _
"Region: " & objOperatingSystem.Locale & vbCrLf & _
"Hersteller: " & objOperatingSystem.Manufacturer & vbCrLf & _
"Typ: " & objOperatingSystem. OSType & vbCrLf & _
"Version: " & objOperatingSystem.Version & vbCrLf & _
"Service Pack: " & objOperatingSystem.ServicePackMajorVersion & _
"." & objOperatingSystem.ServicePackMinorVersion & vbCrLf & _
"Windows-Verzeichnis: " & objOperatingSystem.WindowsDirectory
Next

Bild 3: Die Detailinformationen zum installierten Betriebssystem.

Das Skript wirkt auf den ersten Blick etwas unlogisch, weil ja nur ein Betriebssystem vorhanden sein kann, aber dennoch zunächst eine Sammlung der entsprechenden Objekte erstellt und in einer Schleife durchlaufen wird. Dieser Ansatz hat seine Ursache darin, dass die Grundlogik von WMI darauf ausgelegt ist, Informationen über eine Gruppe von Objekten zu ermitteln und die Betriebssysteme, von denen es eben nur
eines gibt, einen Sonderfall darstellen.

Auch hier lohnt sich wieder ein Blick auf die weiteren Methoden und Eigenschaften – im Listing werden nur Eigenschaften ausgelesen. Die vier Methoden sind:

Mit Hilfe dieser Methoden kann also beispielsweise auch der gezielte Shutdown oder Neustart verschiedener Server veranlasst werden, was vor allem in Testumgebungen hilfreich sein kann, wenn mit dem Windows Server 2003 gearbeitet wird und die Eingabe von Informationen über den Grund des Herunterfahrens vermieden werden soll.


Neben den Informationen aus dem Listing lassen sich mit den Eigenschaften noch viele weitere Informationen ermitteln. Dazu gehören unter anderem:

Wie auch bei den Diensten sind alle Eigenschaften nur lesbar und können nicht modifiziert werden. Sie können aber für viele Zwecke eingesetzt werden. So ist die Abfrage der Statusinformationen beispielsweise zu DEP interessant, um zu ermitteln, welche Systeme überhaupt schon hardwareseitig diese Technologie unterstützen.

Das Ereignisprotokoll

Auch wenn in der Regel über die Anwendung Ereignisanzeige auf das Ereignisprotokoll zugegriffen wird, gibt es auch Fälle, in denen Skripts die bessere Lösung sind. Das gilt vor allem für das Troubleshooting, wenn mögliche relevante Ereignisse bekannt sind und zusammen mit anderen Systeminformationen ausgewertet werden sollen, um die Ursache von Problemen zu erkennen und sie unter Umständen sogar zu beseitigen. So könnten beispielsweise Statusinformationen von Diensten zusätzlich erfragt werden.
Typischerweise wird man solche Anwendungen allerdings nicht isoliert entwickeln, sondern beispielsweise als Erweiterungen von Anwendungen wie dem Microsoft Operations Manager (MOM).

Listing 3: Ein Skript für das Auslesen von Ereignisinformationen
strComputer = "."
Set wbemServices = GetObject("winmgmts:\\" & strComputer)
Set wbemObjectSet = wbemServices.InstancesOf("Win32_NTLogEvent")
For Each wbemObject In wbemObjectSet
WScript.Echo "Logdatei: " & wbemObject.LogFile & vbCrLf & _
"Satznummer: " & wbemObject.RecordNumber & vbCrLf & _
"Typ: " & wbemObject.Type & vbCrLf & _
"Erstellt am: " & wbemObject.TimeGenerated & vbCrLf & _
"Quelle: " & wbemObject.SourceName & vbCrLf & _
"Kategorie: " & wbemObject.Category & vbCrLf & _
"Kategorieinfo: " & wbemObject.CategoryString & vbCrLf & _
"Ereignis: " & wbemObject.EventCode & vbCrLf & _
"Benutzer: " & wbemObject.User & vbCrLf & _
"Computer: " & wbemObject.ComputerName & vbCrLf & _
"Nachricht: " & wbemObject.Message & vbCrLf
Next

Bild 4: Einträge aus dem Ereignisprotokoll können ebenfalls mit Hilfe von Skripts abgefragt werden.

Das Listing 3 enthält ein einfaches Beispiel für eine solche Anwendung. Es ist aber auch ein gutes Beispiel dafür, wann die Grundstruktur an ihre Grenzen stößt. Sie sollten das Skript – wenn überhaupt – nur in der Form

cscript skriptname.vbs

ausführen. Da es alle Ereignisse ausliest und für jedes Ereignis eine Ausgabe erzeugt, werden bei Verwendung von wscript.exe unter Umständen mehrere tausend Fenster angezeigt. Sie können allerdings den Windows Scripting Host (WSH) über den Task-Manager beenden, falls Sie mit dieser Situation konfrontiert werden sollten. Aber auch an der Befehlszeile erhalten Sie keine nutzbaren Ergebnisse mehr. Sie müssen in diesem Fall also unbedingt mit Abfragen arbeiten. Am einfachsten geht das, indem solche Abfragen in das Basisskript integriert werden (Listing 4). Natürlich könnten die Informationen beispielsweise für die Ereignis-ID auch aus Eingabefeldern übernommen werden.

Listing 4: Das Skript mit einer Abfrage
strComputer = "."
Set wbemServices = GetObject("winmgmts:\\" & strComputer)
Set wbemObjectSet = wbemServices.InstancesOf("Win32_NTLogEvent")
For Each wbemObject In wbemObjectSet
If wbemObject.LogFile = "Application" AND wbemObject.Eventcode = 1058 Then
WScript.Echo "Logdatei: " & wbemObject.LogFile & vbCrLf & _
"Satznummer: " & wbemObject.RecordNumber & vbCrLf & _
"Typ: " & wbemObject.Type & vbCrLf & _
"Erstellt am: " & wbemObject.TimeGenerated & vbCrLf & _
"Quelle: " & wbemObject.SourceName & vbCrLf & _
"Kategorie: " & wbemObject.Category & vbCrLf & _
"Kategorieinfo: " & wbemObject.CategoryString & vbCrLf & _
"Ereignis: " & wbemObject.EventCode & vbCrLf & _
"Benutzer: " & wbemObject.User & vbCrLf & _
"Computer: " & wbemObject.ComputerName & vbCrLf & _
"Nachricht: " & wbemObject.Message & vbCrLf
End If
Next

Das Skript unterscheidet sich bisher nur minimal vom vorigen. Hier ist allerdings die Frage, ob man nicht mit der Methode ExecQuery wesentlich einfacher und besser arbeiten könnte. Das modifizierte Skript hätte in diesem Fall das Aussehen aus Listing 5.

Listing 5: Das Skript bei Verwendung von ExecQuery
strComputer = "."
Set wbemServices = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set wbemObjectSet = wbemServices.ExecQuery("SELECT * From Win32_NTLogEvent Where
LogFile = 'Application' AND EventCode = 1058")
For Each wbemObject In wbemObjectSet
WScript.Echo "Logdatei: " & wbemObject.LogFile & vbCrLf & _
"Satznummer: " & wbemObject.RecordNumber & vbCrLf & _
"Typ: " & wbemObject.Type & vbCrLf & _
"Erstellt am: " & wbemObject.TimeGenerated & vbCrLf & _
"Quelle: " & wbemObject.SourceName & vbCrLf & _
"Kategorie: " & wbemObject.Category & vbCrLf & _
"Kategorieinfo: " & wbemObject.CategoryString & vbCrLf & _
"Ereignis: " & wbemObject.EventCode & vbCrLf & _
"Benutzer: " & wbemObject.User & vbCrLf & _
"Computer: " & wbemObject.ComputerName & vbCrLf & _
"Nachricht: " & wbemObject.Message & vbCrLf
Nex

Die Struktur ändert sich dadurch kaum. Die zusätzliche Angabe von root\cimv2 wäre nicht zwingend erforderlich. Interessant ist vor allem die Auswahl. Man vermeidet dadurch Schleifen und arbeitet stattdessen mit WQL (WMI Query Language), also der speziellen SQL-Variante bei WMI. Die Ausgabe ist identisch. Innerhalb der Abfragen lassen sich auch Variablen einsetzen. Damit werden die Skripts deutlich übersichtlicher. Ein Beispiel findet sich in Listing 6.

Listing 6: Die verstärkte Nutzung von Variablen
strComputer = "."
strNameSpace = "\root\cimv2"
strQueryClass = "Win32_NTLogEvent"
strQueryWhere = "LogFile = 'Application' AND EventCode = 1058"
Set wbemServices = GetObject("winmgmts:\\" & strComputer & strNameSpace)
Set wbemObjectSet = wbemServices.ExecQuery("SELECT * From " & strQueryClass & "
Where " & strQueryWhere)
For Each wbemObject In wbemObjectSet
WScript.Echo "Logdatei: " & wbemObject.LogFile & vbCrLf & _
"Satznummer: " & wbemObject.RecordNumber & vbCrLf & _
"Typ: " & wbemObject.Type & vbCrLf & _
"Erstellt am: " & wbemObject.TimeGenerated & vbCrLf & _
"Quelle: " & wbemObject.SourceName & vbCrLf & _
"Kategorie: " & wbemObject.Category & vbCrLf & _
"Kategorieinfo: " & wbemObject.CategoryString & vbCrLf & _
"Ereignis: " & wbemObject.EventCode & vbCrLf & _
"Benutzer: " & wbemObject.User & vbCrLf & _
"Computer: " & wbemObject.ComputerName & vbCrLf & _
"Nachricht: " & wbemObject.Message & vbCrLf
Next

In diesem Fall gibt es zu Beginn verschiedene Definitionen. Die Variablen werden in den beiden Set-Anweisungen verwendet und sorgen dafür, dass auf die gewünschten Daten zugegriffen wird. Diese Struktur des Skripts hat den großen Vorteil, dass es leichter modifiziert werden kann, weil es übersichtlicher ist. Auch ein Ausbau beispielsweise mit Eingabefeldern, in denen die Where-Klausel der Abfrage eingegeben wird, ist wesentlich einfacher zu bewerkstelligen.

Die Klasse Win32_NTLogEvent ist nur eine von mehreren Klassen rund um die Ereignisprotokollierung.
Insgesamt kennt WMI hier fünf Klassen:

Installierte Software

Über WMI lassen sich auch Informationen zur installierten Software ermitteln. Ein Beispiel dafür liefert Listing 7.

Listing 7: Die Abfrage der installierten Software (Quelle:
Microsoft)
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.CreateTextFile("c:\scripts\software.tsv", True)
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colSoftware = objWMIService.ExecQuery _
("SELECT * FROM Win32_Product")
objTextFile.WriteLine "Caption" & vbtab & _
"Description" & vbtab & "Identifying Number" & vbtab & _
"Install Date" & vbtab & "Install Location" & vbtab & _
"Install State" & vbtab & "Name" & vbtab & _
"Package Cache" & vbtab & "SKU Number" & vbtab & "Vendor" & vbtab _
& "Version"
For Each objSoftware in colSoftware
objTextFile.WriteLine objSoftware.Caption & vbtab & _
objSoftware.Description & vbtab & _
objSoftware.IdentifyingNumber & vbtab & _
objSoftware.InstallLocation & vbtab & _
objSoftware.InstallState & vbtab & _
objSoftware.Name & vbtab & _
objSoftware.PackageCache & vbtab & _
objSoftware.SKUNumber & vbtab & _
objSoftware.Vendor & vbtab & _
objSoftware.Version
Next
objTextFile.Close

In diesem Fall werden die Informationen in eine Textdatei geschrieben, was beispielsweise auch für das Auslesen von Ereignissen eine sinnvolle Lösung ist. Wichtig ist vor allem die Klasse, auf die zugegriffen wird. In diesem Fall wird mit Win32_Product gearbeitet. Diese Klasse gehört zu der großen Gruppe der Installed Application Classes, also von Klassen rund um das Management von installierten Anwendungen.

Zu den Methoden dieser Klasse gehören unter anderem:

Mit den verschiedenen Methoden und Eigenschaften lässt sich die Software auf Systemen nicht nur effizient inventarisieren, sondern auch konfigurieren. In den meisten Fällen wird man dazu zwar spezialisierte Lösungen für die Softwareverteilung verwenden, das Scripting kann aber beispielsweise für die Erweiterung solcher Lösungen oder für spezielle Anwendungen hilfreich sein.

Laufende Prozesse

Mit Hilfe von WMI kann aber nicht nur überprüft werden, welche Anwendungen vorhanden sind. Auch die laufenden Anwendungen, also die Prozesse, können abgefragt werden. Es gibt beispielsweise im Resource Kit verschiedene Tools, mit denen sich Prozessinformationen ermitteln lassen. Solche Tools lassen sich mit WMI-Skripts relativ einfach selbst entwickeln und bieten dann exakt die Funktionalität, die benötigt wird. Das Listing 8 zeigt ein Beispiel für ein solches Skript. Das Skript ist noch sehr „minimalistisch“ in seiner Form. Es ermittelt nur, ob ein Prozess läuft oder nicht. Dazu wird die Eigenschaft Count verwendet, die die Anzahl der laufenden Prozesse ausgibt. Auch hier lohnt sich wieder ein Blick auf die Methoden und Eigenschaften sowie die verwandten Klassen. Bei den Methoden findet sich unter anderem Terminate, mit der ein bestimmter Prozess beendet werden kann. Mit SetPriority kann sogar, entsprechende Berechtigungen vorausgesetzt, die Priorität eines Prozesses verändert werden. Wichtig sind aber vor allem die Eigenschaften. Hier gibt es unter anderem Kernel-ModeTime für die Ausführungszeit im Kernel-Modus des Betriebssystems, PeakWorkingSetSize für den maximal konsumierten Hauptspeicher,
ThreadCount für die Anzahl der Threads in diesem Prozess oder WriteOperationCount für die Anzahl der durchgeführten Schreiboperationen – also viele Eigenschaften, mit denen sich Details zum Verhalten des Prozesses, zur Speichernutzung und zur Performance erfragen lassen.

Listing 8: Skript für den Zugriff auf Prozessinformationen
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colProcesses = objWMIService.ExecQuery _
("SELECT * FROM Win32_Process WHERE Name = 'iexplore.exe'")
If colProcesses.Count = 0 Then
Wscript.Echo "Anwendung läuft nicht."
Else
Wscript.Echo "Anwendung läuft."
End If


Neben verschiedenen anderen Klassen, mit denen weitere Informationen zu Prozessen ermittelt und ausgeführte Prozesse überwacht werden können, ist vor allem noch die Klasse Win32_Thread interessant. Über diese kann auf Daten zu den Threads, also den Ausführungseinheiten innerhalb von Prozessen, zugegriffen werden. Die Zuordnung zwischen Prozessen und Threads erfolgt über die Eigenschaften Handle der Klasse Win-32_Process beziehungsweise ProcessHande der Klasse Win32_Thread.

Namensbereiche, Klassen, Methoden

WMI kann aber auch genutzt werden, um mehr über WMI zu erfahren. Ein wichtiges Konzept bei WMI sind die so genannten Namespaces. Ein Namespace definiert einen Bereich von Informationen. In der Regel wird mit dem Namespace CIMv2 gearbeitet. CIM steht dabei für Common Information Model, eine standardisierte Struktur für die Bereitstellung von Informationen über Computer. Neben diesem Namensbereich gibt es aber bei WMI etliche weitere Namensbereiche, die sich über ein einfaches Skript ermitteln lassen.

Bild 5: Die Ausgabe von einfachen Prozessinformationen.

Das Skript ist sehr einfach und erfragt nur die verschiedenen Einträge für die Namespaces unterhalb von root. Die Länge der Liste (Bild 6) variiert in Abhängigkeit der installierten WMI-Provider (und damit Anwendungen) und des Betriebssystems.

Bild 6: Die Liste der WMI-Namespaces auf einem Windows Server 2003.

Listing 9: Skript für die Ermittlung der Namensbereiche (Quelle:
Microsoft)
strComputer = "."
Set objServices = GetObject("winmgmts:\\" & strComputer & "\root")
Set colNameSpaces = objServices.InstancesOf("__NAMESPACE")
For Each objNameSpace In colNameSpaces
WScript.Echo objNameSpace.Name
Next

Da die einzelnen Namespaces wiederum hierarchisch organisiert sind, kann man auch noch die untergeordneten Bereiche ermitteln. Das bringt aber nicht so viel Erkenntnisgewinn. Reizvoller ist die Abfrage der Klassen, die es in Namespaces gibt. Auch hier handelt es sich wieder um ein Skript, das unbedingt über cscript.exe ausgeführt werden oder seine Ergebnisse in eine Datei schreiben sollte, da die ermittelten Informationen recht umfangreich sind. Listing 10 zeigt ein Beispiel für ein solches Skript.

Listing 10: Skript für die Ausgabe aller Klassen in einem
Namespace
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colClasses = objWMIService.SubclassesOf()
For Each objClass In colClasses
WScript.Echo objClass.Path_.Path
Next

Ebenso können über Skripts auch die Methoden und Eigenschaften von Klassen ermittelt werden. In der Regel macht es aber mehr Sinn, die Dokumentation zu WMI zu verwenden, in der alle diese Informationen bereits enthalten sind. Die URL wurde bereits weiter oben in diesem Artikel genannt.

Asynchrone und synchrone Zugriffe

Bei WMI-Abfragen wird zwischen asynchronen und synchronen Zugriffen unterschieden. Eine synchrone Abfrage behält die Kontrolle über die Anwendung, solange die Abfrage ausgeführt wird. Das bedeutet, dass die weiteren Verarbeitungsschritte erst ausgeführt werden können, wenn die Abfrage vollständig bearbeitet wurde – was unter Umständen sehr lange dauern kann, wenn man beispielsweise Ereignisse aus dem Ereignisprotokoll ausliest. Dafür ist die Verwendung solcher Abfragen sehr einfach.

Die meisten Methoden, die nicht explizit asynchron arbeiten, nutzen aber einen so genannten semisynchronen Modus. In diesem läuft die Anwendung weiter, während noch Informationen ermittelt werden. Diese werden jeweils an die weiteren Elemente der Anwendung übergeben. Allerdings kann das bei sehr großen Abfragen zu Lastproblemen führen. Zu den Methoden, die automatisch semisynchron ausgeführt werden, gehören ExecQuery und InstancesOf, also die in den Beispielen üblicherweise verwendeten Methoden.

Das wird beispielsweise beim Auslesen von Daten aus dem Ereignisprotokoll deutlich. Dort werden nicht erst alle Ereigniseinträge ausgelesen. Die Anzeige der Einträge beginnt vielmehr unmittelbar, während im Hintergrund weiter Daten aus dem Ereignisprotokoll gelesen werden. Daher muss man sich in den meisten Fällen auch nicht darum kümmern, ob nun synchron oder asynchron gearbeitet wird. Die automatische semisynchrone Verarbeitung löst die meisten Probleme. Nur die drei Methoden

sind generell synchron. Von den ersten beiden Methoden gibt es aber mit DeleteAsync und Exec MethodAsync auch asynchrone Varianten, ebenso wie mit ExecQueryAsync oder InstancesOf-Async.

Falls explizit eine asynchrone Verarbeitung bevorzugt wird, steigt der Programmieraufwand stark an. In diesem Fall kommt ein so genannter Sink zum Einsatz, in dem die Ergebnisse der Verarbeitung geschrieben werden, während das Programm weiter ausgeführt wird. Die asynchronen Methoden erzeugen Ereignisse, die wiederum über Subroutinen im Skript abgefangen werden müssen. Dazu zählt beispielsweise onCompleted mit Informationen zur Ausführung der asynchronen Methode.

Asynchrone Methoden sollten nur verwendet werden, wenn die Abfragen so komplex sind, dass die Ausführung der Skripts mit semisynchronen Methoden in der Praxis zu Fehlern führt. Das ist aber nur selten der Fall. Umfassende Informationen zur Verwendung von asynchronen Aufrufen finden sich unter

http://msdn.microsoft.com/library/enus/wmisdk/wmi/making_an_asynchronous_call_with_vbscri
pt.asp

Dort wird schrittweise erläutert, wie asynchrone Aufrufe unter Verwendung von VBscript durchgeführt werden können.

Die Serie hat verschiedene Aspekte zu WMI vorgestellt. Dabei wurde auch deutlich, dass WMI eine der mächtigsten Entwicklungsschnittstellen von Windows ist, die in sehr großem Umfang über Skripts genutzt werden kann. Die Beispiele erschließen dabei nur die Grundlagen von WMI, auf denen eigene Anwendungen aufbauen können.

In zukünftigen Ausgaben von Expert’s inside Windows NT/2000 werden weitere Beispiele vorgestellt, mit denen konkrete Herausforderungen im Systemmanagement mit Hilfe von Skripts gelöst werden. Dabei werden noch mehr Details zu WMI auf der einen Seite und VBscript auf der anderen Seite vorgestellt werden. Zu den Themen, die dabei besprochen werden, zählen unter anderem erweiterte Funktionen für die Eingabe von Informationen.

Vorschläge für Skripts erwünscht
Um die weiteren Beiträge zu diesem Thema möglichst praxisgerecht gestalten zu können, können Sie einerseits Vorschläge für Problemstellungen, die mit Skripts gelöst werden sollen, und andererseits fertige
Skripts an den Autor mailen, die dann im Rahmen von Artikeln – natürlich unter Nennung des Erstellers des Skripts – vorgestellt werden. Die E-Mail-Adresse ist martin@kuppinger.de.