WMI ist eine mächtige Schnittstelle um Windows Systeme zu verwalten. Dadurch ist der Zugriff auf Dinge möglich, für die es vielleicht sonst gar keine eigenen PowerShell Cmdlets gibt. Teilweise können wir so mehr Infos abrufen, als die Standard-Cmdlets liefern. Das geht sowohl lokal, als auch remote.
Deprecated: Die alten WMI Cmdlets
Es gibt ein paar ältere Cmdlets, die allerdings für Neuentwicklungen nicht empfohlen werden. Aber vielleicht stoßt ihr in älteren Skripten mal darüber, also jetzt habt ihr schon mal davon gehört - die existieren zumindest.
|
|
CIM Cmdlets
Stattdessen macht es Sinn, bei Neuentwicklungen auf die CIM Cmdlets zu setzen. CIM steht für “Common Information Model” und ist quasi der eigentliche technische Standard. Und WMI ist die CIM Implementierung von Microsoft, die den Standard dann teilweise noch ein bisschen erweitert.
|
|
Auch wenn da nur im Namen nur CIM steht und nicht WMI - damit können wir auf WMI zugreifen.
WMI Daten abfragen
Es gibt verschiedene Möglichkeiten Infos per WMI abzufragen. Zum Beispiel mit der WMI Query Language kurz WQL - eine Art von SQL. Es gibt einfachere Wege um Infos per WMI abzufragen, aber WMI Queries wurden z.B. gerne in alten VB-Skripten verwendet, oder auch bei WMI Filtern für Gruppenrichtlinien. Wenn ihr also bereits einen WMI Query habt, dann könnt ihr den einfach in PowerShell weiterverwenden.
Eine Abfrage mit einem WMI Query könnt ihr mit dem Cmdlet Get-CimInstance
ausführen.
|
|
Das bedeutet im Grunde: Zeige mir alle Eigenschaften von allen Instanzen der Klasse Win32_BIOS
.
Eine etwas PowerShelligere Möglichkeit um WMI abzufragen, wäre so:
|
|
Bei beiden Varianten werden alle Eigenschaften zurückgeliefert - auch wenn das nicht sofort ersichtlich ist. Mit einer pipe zu | Select-Object *
könnten alle Eigenschaften des zurückgelieferten Objekts sichtbar gemacht werden. Aber in der PowerShell gilt der Grundsatz: Wenn es möglich und sinnvoll ist, sollte soweit links wie es geht gefiltert werden. Das bezieht sich sowohl auf die Auswahl von Objekten, als auch auf die Auswahl der Objekteigenschaften.
Für die Auswahl der Objekteigenschaften können wir den Parameter -Property
verwenden. Also z.B.:
|
|
Jetzt kann ich alles mögliche mit den abgerufenen Eigenschaften machen. Beispielsweise die Rückgabe in eine Variable laden oder direkt auf einzelne Eigenschaften der Rückgabe zugreifen.
|
|
WMI Daten filtern
Wenn ihr bei einer WMI Abfrage genauer filtern möchtet, dann geht das wahlweise mit einem kompletten WMI Query, oder mit dem -Filter
Parameter. Die Syntax von WMI Filtern ist anders als sonst in PowerShell. Meiner Meinung nach eigentlich sogar ein bisschen intuitiver. Aber wenn man die ganze Zeit PowerShell verwendet, dann ist es doch wieder etwas ungewohnt.
Es gibt die einfachen Vergleichsoperatoren:
Operator | Description |
---|---|
= | Equal to |
< | Less than |
> | Greater than |
<= | Less than or equal to |
>= | Greater than or equal to |
!= or <> | Not equal to |
Siehe dazu: https://learn.microsoft.com/en-us/windows/win32/wmisdk/wql-operators
Und auch den LIKE
Operator für eine Platzhaltersuche. Siehe dazu: https://learn.microsoft.com/en-us/windows/win32/wmisdk/like-operator
|
|
Mit WQL geht noch weitaus mehr, ich habe aber das bisher noch nicht wirklich gebraucht. Falls ihr euch dafür interessiert, schaut mal in die Dokumentation bei Microsoft: https://learn.microsoft.com/en-us/windows/win32/wmisdk/wql-sql-for-wmi
Verknüpfte Instanzen
Was auch noch hilfreich sein kann: Verknüpfte Klassen - beziehungsweise eigentlich asoziierte Instanzen. Zum Beispiel rufe ich mir erstmal alle physischen Netzwerkkarten an meinem Gerät ab:
|
|
Anschließend pipe ich mir das in Get-CimAssociatedInstance
um alle damit zusammenhängenden Instanzen zu sehen:
|
|
Anhand der Daten die jetzt ausgegeben werden, kann ich vielleicht ja schon sehen, dass hier etwas interessantes vorliegt. Ansonsten können wir uns diese Ausgabe auch noch an Select-Object
pipen, um z.B. nur die Namen der Klassen zu sehen:
|
|
Oder um alle Eigenschaften zu sehen, die waren nämlich vorher nicht alle zu sehen:
|
|
Wenn wir dadurch herausgefunden haben, dass uns eine bestimmte Klasse interessiert, dann können wir unseren ursprünglichen Abruf von Get-CimAssociatedInstance
anpassen und nur noch diese eine Klasse dadurch abrufen:
|
|
Dadurch konnte ich mir jetzt die Netzwerkkonfiguration für eine bestimmte Netzwerkkarte in meinem Computer anzeigen lassen.
Remote WMI
Am einfachsten geht Remote WMI, wenn unser aktuell angemeldeter User auch Admin-Rechte auf dem Remote System hat. Zum Beispiel:
|
|
Alternativ können wir eine separate CimSession aufbauen und dabei dann andere Zugangsdaten angeben.
|
|
Wenn ihr mehrere WMI Aktionen gegen ein Remote System ausführen wollt, dann ist es übrigens effizienter, erstmal eine Session aufzubauen und dann die ganzen Befehle mit dem -CimSession
Parameter auszuführen. Wenn bei Get-CimInstance
der -ComputerName
Parameter genutzt wird, dann wird nämlich jedes mal neu eine Verbindung aufgebaut, sich authentifiziert, der Befehl ausgeführt und am Ende die Verbindung beendet. Eine CimSession hingegen besteht weiter, bis sie aktiv beendet wird.
WSMAN und DCOM
WMI Remoting mit den CIM Befehlen verwendet im Hintergrund standardmäßig das WSMAN Protokoll. Falls Remote WMI bei euch noch nicht direkt funktioniert, dann könnt ihr es mit dem Cmdlet Enable-PSRemoting
aktivieren. Die älteren WMI-Cmdlets verwenden übrigens DCOM statt WSMAN, was aber unter modernen Systemen im Standard von der Windows Firewall blockiert wird. Es wäre aber auch mit den CIM-Cmdlets möglich DCOM zu verwenden, falls es nötig ist. Die Details dazu findet ihr bei Microsoft Learn.
Mehrere Remote Systeme
Es ist auch möglich mit mehreren remote Systemen aufeinmal zu arbeiten. Dazu müsst ihr zunächst einmal mehrere CimSessions aufbauen, und sie dann an Get-CimInstance
übergeben.
|
|
Verbindung trennen
Wenn ihr eure Remotetätigkeiten abgeschlossen habt, dann solltet ihr auch die Verbindungen wieder trennen. Am einfachsten geht das per:
|
|
WMI Methoden ausführen
Mit WMI können wir aber nicht nur Infos abrufen, sondern auch Methoden ausführen. Teilweise überschneiden die sich inhaltlich auch mit normalen PowerShell Cmdlets oder mit Methoden die per .NET verfügbar sind. Es kann aber auch sein, dass genau die Sache die ihr machen wollt, nur per WMI verfügbar ist.
Zum Beispiel rufe ich mir erstmal eine CIM Instanz ab, die sich auf einen bestimmten Drucker bezieht. Anschließend pipe ich die Instanz an Invoke-CimMethod
um den Drucker als Standarddrucker zu definieren.
|
|
Ich musste jetzt hier zwei Cmdlets verwenden, weil Invoke-CimMethod
nicht den -Filter
Parameter unterstützt, der bei Get-CimInstance
verfügbar ist. Ich könnte aber den -Query
Parameter verwenden und einen WMI Query angeben, das hingegen wird von Invoke-CimMethod
unterstützt.
|
|
Es muss aber auch nicht unbedingt eine bestimmte WMI Objektinstanz angesprochen werden. Einige Klassen unterstützen auch direkte Methodenaufrufe. Zum Beispiel:
|
|
WMI Remote Methodenaufrufe
Grundsätzlich unterstützt Invoke-CimMethod
auch das zuvor gezeigte Remoting. Also auch hier könnte wahlweise -ComputerName
oder -CimSession
verwendet werden.
|
|
Wichtig: Wenn Prozesse remote gestartet werden, laufen die nicht sichtbar auf dem Desktop. Im Task Manager, oder zum Beispiel per Get-Process
könnte man erkennen, dass die Prozesse laufen. Für das Beispiel notepad.exe
ist das vielleicht nicht so sinnvoll, für andere Prozesse aber schon ✌️
WMI Methoden herausfinden
Wenn ihr schon eine WMI-Objektinstanz habt, dann könnt ihr direkt in der PowerShell schauen, welche Methoden zur Verfügung stehen:
|
|
WMI Objektinstanzen löschen
Es gibt auch noch das Cmdlet Remove-CimInstance
mit der WMI Objektinstanzen gelöscht werden können. Das ist in der Regel ein ⚠️ destruktiver Vorgang ⚠️, bei dem nicht einfach nur die Repräsentation des Objekts in der PowerShell entfernt wird, sondern das tatsächliche dahinterliegende Objekt wird zerstört. Also z.B. wenn ich die Objektinstanz eines laufenden Prozesses lösche, dann wird der Prozess beendet.
|
|
Was genau passiert, kommt natürlich auf die konkrete Klasse an. Aber am besten verwendet ihr das Remove-CimInstance
Cmdlet mit äußerster Vorsicht.
WMI Klassen, Eigenschaften und Methoden herausfinden
Um alle WMI Klassen aufzulisten, die es am System gibt, könnt ihr das Cmdlet Get-CimClass
verwenden. Je nach System sind das auch unterschiedlich viele, aber auf einem modernen Windows 11 System locker über 2000. Und die ein oder andere Hard- oder Software bringt noch eigene Klassen mit.
|
|
Zu den Namen der Klassen:
- Fängt mit
__
an: Systemklasse - Fängt mit
MSFT
an: Systemklasse - Fängt mit
CIM
an: Basis CIM Klasse (meist gibt es eine bessereWin32
Klasse als Alternative) - ⭐ Fängt mit
Win32
an: Erweiterte WMI Klasse (basiert auf CIM Standard-Klassen) - Fängt mit
Win32_Perf
an: Performance Counter Klasse - Fängt mit
Win32_PnPDevice
an: Plug and Play Device Klasse - ⭐ Fängt komplett anders an: Könnte auch interessant sein
Siehe dazu auch: https://learn.microsoft.com/en-us/windows/win32/wmisdk/wmi-classes
Es gibt teilweise CIM
und Win32
Klassen die sich inhaltlich überschneiden. In der Regel ist die Win32
Klasse dann mächtiger. Zum Beispiel hat die Klasse Win32_Process
bei mir 45 Properties und 7 Methoden, im Gegensatz zur CIM_Process
Klasse, die nur 18 Properties und gar keine Methoden hat.
Die Methoden und Eigenschaften einer Klasse sind in den Eigenschaften CimClassMethods
und CimClassProperties
aufgeführt.
|
|
Ich bevorzuge es aber, mir die Infos in der offiziellen Dokumentation anzuschauen. Wenn ich einfach nach Win32_Process
in einer Suchmaschine suche, dann lande ich schnell bei der richtigen Dokumentation. Vorteil ist: Dort gibt es in der Regel auch Beschreibungen und Beispiele für die Eigenschaften und Methoden.
WMI Namespaces
Wie euch vielleicht bei der Rückgabe von Get-CimClass
aufgefallen ist: Über der Liste der Ergebnisse steht noch: “NameSpace: ROOT/cimv2”.
Die Klassen sind in sogenannten Namespaces einsortiert - so ähnlich wie Ordner im Dateisystem. Zusätzliche Hard- oder Softwares bringen teilweise eigene Namespaces mit, in denen dann zusätzliche WMI Klassen drin sind. root/cimv2
ist einfach der Standard Namespace von Windows. Und wenn wir Get-CimClass
ohne weitere Parameter aufrufen, dann werden uns nur die Klassen in diesem Standard Namespace aufgelistet. Es gibt aber noch mehr Namespaces.
Die Definition der Namespaces kann ich über die System Klasse __Namespace
abrufen, muss aber auch mit angeben, dass ich diese Definition im Namespace root
ansehen möchte (ohne cimv2
, das ist nämlich schon ein Unter-Namespace von root
):
|
|
Auf einem Domänencontroller habe ich auch schon andere Namespaces als auf einem Windows 11 Client. Zum Beispiel gibt es auf meinem DC den Namespace MicrosoftActiveDirectory
.
|
|
Tatsächlich können Namespaces auch noch weitere Namespaces enthalten. Zum Beispiel sind im Standard Namespace root/cimv2
auch noch weitere Unter-Namespaces vorhanden.
Mit einer kleinen selbstgeschriebenen Funktion können wir uns alle Namespaces auflisten.
|
|
Generell spielt sich - meiner Meinung nach - aber auch viel wichtiges in dem Standard Namespace root/cimv2
ab. Aber das kommt natürlich darauf an, was ihr mit WMI gerade machen wollt.
WMI Klassen finden
Falls ihr noch nicht wisst, welche Klasse ihr braucht, könnt ihr mit Get-CimClass
auch suchen. Wenn ihr vermutet, dass der Name der Klasse ein bestimmtes Wort enthält, könnt ihr Wildcards verwenden und suchen:
|
|
Ansonsten gibt es auch noch grafische Tools die dabei helfen können, wie z.B. den WMI Explorer von Vinay Pamnani.