WMI/CIM aus C# und PowerShell verwenden ── Praxisleitfaden für Hardwareinformationen, Prozessüberwachung und Remoteabfragen
· Aktualisiert am: · Go Komura · Windows, C#, .NET, PowerShell, WMI, CIM, Geschäftsanwendungen, Windows-Entwicklung
Änderungsverlauf (Erstfassung, veröffentlicht am 1. Aug 2026)
- Erstveröffentlichung
Diesen Artikel zitieren(DOI (registriertes Archiv): 10.5281/zenodo.22175744)
Die folgenden DOIs verweisen auf bereits archivierte Versionen, die vom aktuellen Text abweichen können. Verwenden Sie die URL dieser Seite, um auf den aktuellen Text zu verweisen.
Go Komura (2026). WMI/CIM aus C# und PowerShell verwenden ── Praxisleitfaden für Hardwareinformationen, Prozessüberwachung und Remoteabfragen. KomuraSoft LLC. https://comcomponent.com/de/blog/wmi-cim-practical-guide/
- DOI (registriertes Archiv)
- 10.5281/zenodo.22175744
- DOI (zuletzt registrierte Version)
- 10.5281/zenodo.22175745
„Ich möchte die Seriennummer und den Modellnamen des PCs anzeigen.“ „Ich möchte den freien Speicherplatz auf einem Server prüfen.“ „Ich möchte erkennen, wenn ein Prozess startet.“ In Windows-Geschäftsanwendungen und Verwaltungswerkzeugen lassen sich solche Informationen über WMI/CIM auf einem gemeinsamen Weg behandeln.
CIM ist das Standardmodell für Verwaltungsinformationen, WMI die Windows-Verwaltungsgrundlage, die diesen Standard nutzt. Die CIM-Cmdlets von PowerShell und die C#-APIs sind die Einstiege in diese Grundlage.1
flowchart TB
accTitle: Typische Anforderungen und WMI/CIM
accDescr: Anzeige von Seriennummer und Modellname, Überwachung des freien Datenträgerplatzes, Erkennung von Prozessstarts und Abfrage entfernter PCs sind typische Anforderungen von Geschäftsanwendungen, deren Standardantwort WMI ist, das den CIM-Standard zur Darstellung von Verwaltungsinformationen nutzt
r1["Seriennummer und Modellname"] --> ans["WMI (Grundlage, die den CIM-Standard nutzt)"]
r2["Überwachung des freien Datenträgerplatzes"] --> ans
r3["Erkennung von Prozessstarts"] --> ans
r4["Abfrage entfernter PCs"] --> ans
Abbildung 1: Die Standardantwort auf vier typische Anforderungen von Geschäftsanwendungen ist WMI/CIM.
Verwirrend ist, dass es mehrere Einstiege gibt. Suchergebnisse mischen das alte Get-WmiObject mit Get-CimInstance, und in C# gibt es System.Management und Microsoft.Management.Infrastructure. Die alten WMI-Cmdlets funktionieren unter Windows PowerShell 5.1, in PowerShell 7 gibt es sie nicht.2
Dieser Artikel richtet sich an C#-/PowerShell-Entwickler, die Hardwareinformationen abrufen, Prozesse überwachen und entfernte PCs abfragen. Die Reihenfolge ist: entscheiden, ob WMI das richtige Werkzeug ist, in PowerShell ausprobieren, die Verbindungsvoraussetzungen prüfen, in C# einbauen und dann Überwachung und Störungsbehandlung vervollständigen. Beispiele und Hinweise stützen sich auf Primärquellen mit Stand August 2026.
1. Zuerst das Fazit: Den Einstieg nach Zweck und Ziel wählen
Neues PowerShell schreiben Sie mit den CIM-Cmdlets, und die C#-API wählen Sie nach dem Zweck. Arbeit, für die bereits ein eigener Mechanismus existiert, müssen Sie nicht auf WMI schieben.
| Entscheidung oder Aufgabe | Grundsatz | Kapitel |
|---|---|---|
| Entscheiden, ob WMI zu verwenden ist | Für übergreifende Informationsabfrage und Remoteabfragen nutzen; für Einstellungen und hochfrequente Leistungsüberwachung einen eigenen Mechanismus wählen | Kapitel 2 |
| Entscheiden, was abgefragt wird | Namensraum, Klasse und Eigenschaften wählen und das Ziel mit WQL eingrenzen. Der Alltagswert ist root/CIMV23 |
Kapitel 3 und 4 |
| In PowerShell ausprobieren | Mit Get-CimInstance lesen und mit Invoke-CimMethod handeln. Auch neuen Code für 5.1 auf der CIM-Seite schreiben2 |
Kapitel 4 |
| Auf entfernte Rechner ausweiten | WSMan/WinRM als Grundlage, eine CIM-Sitzung für mehrere Vorgänge gegen dasselbe Ziel wiederverwenden. DCOM wählen, wenn nötig34 | Kapitel 5 |
| In C# einbauen | System.Management für schnelle lokale Abfragen, die MI-API erwägen, wenn Remoteabfragen oder Überwachung eingebaut werden56 |
Kapitel 6 |
| Prozessstarts überwachen | Ein Ereignisabonnement verwenden und Rechte, Aufhebung und erneute Registrierung nach einem Abbruch mitentwerfen78 | Kapitel 7 |
| Klären, warum es langsam ist, den falschen Wert liefert oder eine Klasse nicht findet | Menge und Häufigkeit der Abfragen, Bitzahl des Providers und Konsistenz des Repositorys eingrenzen | Kapitel 8 |
Insbesondere sind etwas auflisten können und seine Ereignisse abonnieren können zwei verschiedene Dinge. Das Abonnementbeispiel für Win32_ProcessStartTrace läuft mit Administratorrechten.7 Greifen Sie nicht aus Gewohnheit zu SELECT * oder zu Polling in kurzen Abständen: Grenzen Sie das Ergebnis mit -Filter, -Property und -KeyOnly auf die benötigten Informationen ein.3
In der Abbildung kennzeichnet eine durchgezogene Linie eine stets geltende Beziehung und eine gestrichelte Linie eine bedingte (die Bedingungen stehen bei jeder Beziehung auf der Detailseite). Die vollständige Liste der Beziehungen (26 insgesamt, mit Beleg und Sicherheitsgrad) und die Definitionen der wichtigsten Konzepte sind auf der Detailseite der Wissenskarte (auf Japanisch) zusammengestellt. Daten: JSON-LD / Turtle
2. Wann WMI/CIM zu verwenden ist und wann ein eigener Mechanismus
WMI ist als einheitliche Leseschnittstelle stark, aber nicht immer die beste Antwort. Hier die praxisnahe Unterscheidung.
| Was Sie tun wollen | Passendes Mittel | Warum nicht WMI |
|---|---|---|
| Hardwareinformationen und OS-Konfiguration abrufen, agentenlose Remoteabfragen | WMI/CIM | Hier liegt die Stärke von WMI. Einheitlicher als einzelne Spezial-APIs |
| Einstellungen der eigenen Anwendung lesen und schreiben | Registrierung direkt (Microsoft.Win32.Registry) oder eine Konfigurationsdatei |
Registrierung über WMI ist ein Umweg und zieht das Bitzahl-Problem aus Abschnitt 8.2 mit |
| Hochfrequente, fortlaufende Leistungsüberwachung wie CPU-Auslastung | Leistungsindikatoren (System.Diagnostics.PerformanceCounter und ähnliche) |
Zähler existieren genau dafür. WMI-Polling in kurzen Abständen verliert bei Last und Genauigkeit |
| Einmalige OS-Funktionsaufrufe und Verarbeitung mit geringer Latenz | Die Win32-API (P/Invoke) | WMI trägt den Aufwand über COM und einen Provider |
| Lokale Prozessauflistung und -steuerung, die die Rechte des eigenen Prozesses schon decken | System.Diagnostics.Process |
Immer in der Standardbibliothek, weniger Abhängigkeiten |
| Windows-Verwaltungsfunktionen wie Firewall und Netzwerk konfigurieren | Eigene CIM-basierte Cmdlets wie Get-NetFirewallRule |
Pro Aufgabe aufbereitete Cmdlet-Sätze sind genauer und sicherer als die Suche nach rohen WMI-Klassen |
| Änderungen an Dateien und Ordnern erkennen | FileSystemWatcher |
WMI nicht in einen Bereich bringen, der schon eine eigene API hat |
Die Entscheidungsachse ist einfach: Nutzen Sie den eigenen Mechanismus dort, wo es einen gibt, und WMI/CIM für übergreifende Abfragen und Remoteabfragen. Die Familie Get-NetFirewallRule in der Tabelle ist selbst ein auf CIM aufgebautes Cmdlet-Set — der Nutzen von WMI/CIM, ohne es direkt anzufassen.
flowchart TB
accTitle: Die Entscheidungsachse für das Mittel
accDescr: Die Entscheidungsachse ist, den eigenen Mechanismus dort zu nutzen, wo es einen gibt, und WMI und CIM für übergreifende Abfragen und Remoteabfragen dort, wo es keinen gibt; eigene CIM-basierte Cmdlets sind eine Form, den Nutzen zu erhalten, ohne WMI und CIM direkt anzufassen
q1{"Gibt es einen eigenen Mechanismus?"} -->|Ja| ded["Den eigenen Mechanismus nutzen"]
q1 -->|Nein| wmi["WMI / CIM nutzen"]
wmi -.-> use["Übergreifende Abfragen und Remoteabfragen"]
cmd["Eigene CIM-basierte Cmdlets"] -.-> ben["Nur den Nutzen erhalten"]
Abbildung 2: Den eigenen Mechanismus nutzen, wo es einen gibt, und WMI/CIM für übergreifende und Remoteabfragen.
3. Den Mechanismus klären: Standard, Namensraum, Klasse, WQL
3.1. CIM ist der Standard, WMI die Implementierung unter Windows
Zuerst die Begriffe einmal sortieren.
| Begriff | Was es tatsächlich ist |
|---|---|
| CIM (Common Information Model) | Das Branchenstandardmodell zur Darstellung von Verwaltungsobjekten wie Systemen, Anwendungen, Netzen und Geräten. Festgelegt und gepflegt vom DMTF (Distributed Management Task Force)1 |
| WBEM (Web-Based Enterprise Management) | Eine Brancheninitiative, die Standardtechnologien für den Zugriff auf Verwaltungsinformationen in Unternehmensumgebungen entwickelt1 |
| WMI | Die Microsoft-Implementierung von WBEM. Stellt Verwaltungsobjekte anhand des CIM-Standards dar und ist fest in Windows integriert1 |
| MI (Windows Management Infrastructure) | Die nächste Generation von WMI. Vollständig kompatibel mit dem klassischen WMI; die meisten neuen Provider sind in MI geschrieben1 |
flowchart TB
accTitle: Beziehung zwischen CIM-Standard und WMI-Implementierung
accDescr: Den vom DMTF festgelegten und gepflegten CIM-Standard nutzt die WBEM-Initiative, die Microsoft-Implementierung ist WMI, die nächste Generation MI ist vollständig kompatibel mit dem klassischen WMI, und CIM-APIs verbinden sich alle mit derselben WMI-Grundlage
dmtf["Vom DMTF festgelegt und gepflegt"] --> cim["CIM (Branchenstandardmodell)"]
wbem["WBEM (Brancheninitiative)"] --> wmi["WMI (Microsoft-Implementierung)"]
cim --> wmi
wmi -.-> mi["MI (nächste Generation, vollständig kompatibel)"]
api["CIM-APIs (PowerShell / C#)"] --> wmi
Abbildung 3: CIM ist die Spezifikation, WMI die Implementierung unter Windows. CIM-APIs verbinden sich alle mit derselben WMI-Grundlage.
3.2. Namensraum, Klasse, Provider und WQL als eine Kette lesen
Als Entwickler sind vier Strukturpunkte wichtig.
- Namensraum (namespace): eine Hierarchie, die Klassen bündelt. Für alltägliche Abfragen wird fast ausschließlich root/CIMV2 verwendet, das auch die Vorgabe der CIM-Cmdlets ist.3 Daneben gibt es unter anderem
root\default(etwa den Registrierungsprovider). - Klasse: ein Typ für ein Verwaltungsobjekt, etwa
Win32_ComputerSystem(der Computer selbst),Win32_LogicalDisk(ein logisches Laufwerk) oderWin32_Process(ein Prozess). Windows-spezifische Klassen, die von CIM-Standardklassen (wieCIM_LogicalDisk) erben, tragen das PräfixWin32_.9 - Provider: die Komponente, die den eigentlichen Inhalt einer Klasse bereitstellt. Bei einer Abfrage fragt der Provider das Betriebssystem an Ort und Stelle ab und erzeugt die Werte.
- WQL: eine SQL-ähnliche Abfragesprache. Wie in
SELECT Name, State FROM Win32_Service WHERE StartMode = 'Auto'wird eine Klasse wie eine Tabelle behandelt und eingegrenzt. WQL ist auch die Standardabfragesprache der CIM-Cmdlets.3
OS- und Hardwareinformationen über einheitliche Klassen und eine Abfragesprache lesen zu können — das ist der Wert von WMI. Nicht jede Klasse unterstützt Schreiben oder Vorgänge. Klassen mit Methoden werden mit Invoke-CimMethod angesteuert, Änderungen an schreibbaren Eigenschaften mit Set-CimInstance. Wie die Zuordnungstabelle in Abschnitt 4.1 zeigt, wählen Sie den Einstieg nach dem, was die Klasse anbietet.
flowchart TB
accTitle: Struktur einer WMI-Abfrage
accDescr: Eine WQL-Abfrage zielt auf eine Win32-Klasse im Namensraum root/CIMV2, der Provider, der die Instanzen der Klasse bereitstellt, fragt das Betriebssystem an Ort und Stelle und erzeugt die Werte, und das Ergebnis wird zurückgegeben
wql["Mit WQL abfragen"] --> ns["Namensraum root/CIMV2"]
ns --> cls["Win32_*-Klasse"]
cls --> prov["Provider"]
prov --> osq["Fragt das Betriebssystem an Ort und Stelle"]
osq --> res["Gibt das Ergebnis zurück"]
Abbildung 4: Eine Abfrage folgt Namensraum, dann Klasse, dann Provider, und die Werte entstehen an Ort und Stelle.
4. In PowerShell ausprobieren: Lesen, Methodenaufruf und Bestandsinformationen
Ab hier in PowerShell unter Windows. Auch beim Portieren alten Codes prüfen Sie zuerst die Zuordnung der Cmdlets und den Unterschied bei den Rückgabewerten.
4.1. Neuen Code mit den CIM-Cmdlets schreiben
In PowerShell 6 und später (aktuell PowerShell 7) sind die folgenden WMI-v1-Cmdlets entfernt. Dieselbe Funktionalität stellt das Modul CimCmdlets (WMI v2) bereit.2
| Alt (bis Windows PowerShell 5.1) | Aktuell (CIM-Cmdlets) | Hinweis |
|---|---|---|
Get-WmiObject |
Get-CimInstance |
Die Idee hinter -Filter / -Query ist dieselbe |
Get-WmiObject -List |
Get-CimClass |
Klassen finden und Definitionen prüfen |
Invoke-WmiMethod |
Invoke-CimMethod |
Argumente als Hashtabelle mit -Arguments @{ } |
Register-WmiEvent |
Register-CimIndicationEvent |
Ereignisabonnement (Kapitel 7) |
Set-WmiInstance |
Set-CimInstance |
Schreibbare Eigenschaften ändern |
Remove-WmiObject |
Remove-CimInstance |
Eine Instanz löschen |
Die CIM-Cmdlets funktionieren auch unter Windows PowerShell 5.1, daher vermeidet neuer Code auf der CIM-Seite, auch wenn er unter 5.1 laufen soll, hinterher Migrationskosten. Das Gesamtbild von 5.1 und 7 nebeneinander und der Migration steht in „Unterschiede zwischen Windows PowerShell 5.1 und PowerShell 7“.
flowchart TB
accTitle: Warum neue Skripte mit CIM geschrieben werden
accDescr: Ein mit WMI-Cmdlets geschriebenes Skript läuft unter 5.1, ist ab PowerShell 6 entfernt und muss bei der Migration umgeschrieben werden; CIM-Cmdlets laufen auch unter 5.1, daher bleibt bei neuem Code auf der CIM-Seite keine Migrationskosten
new["Ein neues Skript"] --> q1{"Womit schreiben?"}
q1 -->|WMI-Cmdlets| old["Läuft unter 5.1"]
q1 -->|CIM-Cmdlets| cur["Läuft auch unter 5.1"]
old --> del["In PowerShell 7 entfernt"]
del --> rew["Umschreiben bei der Migration"]
cur --> norew["Keine Migrationskosten"]
Abbildung 5: Neuen Code mit den CIM-Cmdlets schreiben, dann muss bei der Migration zu PowerShell 7 nichts umgeschrieben werden.
4.2. Zeilen und Spalten mit Get-CimInstance eingrenzen
# Klasse angeben (Standardnamensraum root/CIMV2)
Get-CimInstance -ClassName Win32_OperatingSystem
# Nur die WHERE-Klausel in -Filter schreiben (das Schlüsselwort WHERE nicht schreiben)
Get-CimInstance -ClassName Win32_Service -Filter "StartMode = 'Auto' AND State <> 'Running'"
# Nur die benötigten Eigenschaften abrufen, um die übertragene Menge zu senken
Get-CimInstance -ClassName Win32_Process -Property Name, ProcessId, CreationDate
# WQL selbst schreiben mit -Query
Get-CimInstance -Query "SELECT * FROM Win32_Process WHERE Name LIKE 'p%'"
-Filter ist die WQL-WHERE-Klausel selbst, -Property begrenzt die abgerufenen Spalten.3 Der Rückgabewert ist ein CimInstance-Objekt, und Datumseigenschaften (CreationDate, LastBootUpTime usw.) kommen bereits als DateTime zurück.
4.3. Methoden mit Invoke-CimMethod aufrufen
Anders als beim alten Get-WmiObject rufen Sie WMI-Methoden nicht direkt am abgerufenen Objekt auf, daher gehen Methodenaufrufe über Invoke-CimMethod.
flowchart TB
accTitle: Methodenaufruf an einer CimInstance
accDescr: Die von Get-CimInstance zurückgegebene CimInstance kommt mit bereits nach DateTime umgewandelten Datumseigenschaften zurück, ist aber keine Form, auf der WMI-Methoden direkt aufgerufen werden; ein Methodenaufruf erfolgt durch Übergabe der Instanz an Invoke-CimMethod
gci["Get-CimInstance"] --> inst["CimInstance-Objekt"]
inst -.-> dt["Daten bereits nach DateTime umgewandelt"]
inst -.-> nom["WMI-Methoden über einen anderen Einstieg"]
inst --> icm["An Invoke-CimMethod übergeben"]
icm --> call["Methodenaufruf"]
Abbildung 6: WMI-Methoden einer CimInstance nicht direkt aufrufen; den Aufruf durch Übergabe an Invoke-CimMethod ausführen.
# Methode an einer Instanz aufrufen: den Besitzer jedes Prozesses holen
Get-CimInstance -ClassName Win32_Process -Filter "Name = 'notepad.exe'" |
Invoke-CimMethod -MethodName GetOwner
# Statische Methode der Klasse aufrufen: einen Prozess starten
Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{ CommandLine = 'notepad.exe' }
# Klassendefinition (Liste der Eigenschaften und Methoden) prüfen
Get-CimClass -ClassName Win32_Process
4.4. Die Klasse nach der gewünschten Information wählen
| Gewünschte Information | Klasse | Wichtige Eigenschaften |
|---|---|---|
| Hersteller und Modellname | Win32_ComputerSystem |
Manufacturer, Model |
| Seriennummer des Gehäuses | Win32_BIOS |
SerialNumber |
| OS-Ausgabe und Startzeit | Win32_OperatingSystem |
Caption, Version, LastBootUpTime |
| Freier Datenträgerplatz | Win32_LogicalDisk |
DeviceID, FreeSpace, Size, DriveType9 |
| Dienststatus | Win32_Service |
Name, State, StartMode |
| Prozessliste | Win32_Process |
Name, ProcessId, CommandLine |
4.5. Beispiel Bestandsverwaltung: Modell, Seriennummer und freier Datenträgerplatz
# Modellinformationen und Seriennummer (Abgleich mit der PC-Bestandsliste)
$cs = Get-CimInstance -ClassName Win32_ComputerSystem -Property Manufacturer, Model
$bios = Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber
[pscustomobject]@{
Manufacturer = $cs.Manufacturer
Model = $cs.Model
Serial = $bios.SerialNumber
}
# Freier Platz auf lokalen Datenträgern (DriveType = 3)
Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType = 3" |
Select-Object DeviceID,
@{ Name = 'FreeGB'; Expression = { [math]::Round($_.FreeSpace / 1GB, 1) } },
@{ Name = 'SizeGB'; Expression = { [math]::Round($_.Size / 1GB, 1) } }
DriveType = 3 steht für „lokales Laufwerk“ und schließt Wechseldatenträger (2), Netzlaufwerke (4) und CDs (5) aus.9 Sind die Verbindungsvoraussetzungen aus Kapitel 5 erfüllt, ergibt dasselbe Skript über eine CIM-Sitzung gegen jeden Server die Grundlage für agentenlose Datenträgerüberwachung.
flowchart TB
accTitle: Grundlage der agentenlosen Datenträgerüberwachung
accDescr: Die Filterung auf DriveType 3 schließt Wechseldatenträger, Netzlaufwerke und CDs aus, sodass nur lokale Datenträger erfasst werden, und dasselbe Skript über eine CIM-Sitzung gegen jeden Server ergibt die Grundlage für agentenlose Datenträgerüberwachung
scr["Skript zum Abruf des freien Platzes"] --> flt["Auf DriveType = 3 filtern"]
flt -.-> exc["Schließt Wechseldatenträger usw. aus"]
scr --> ses["Über eine CIM-Sitzung"]
ses --> srvs["Gegen jeden Server ausführen"]
srvs --> mon["Agentenlose Überwachung"]
Abbildung 7: Ein auf lokale Datenträger eingegrenztes Skript über eine CIM-Sitzung gegen jeden Server ist die Grundlage der Überwachung.
5. Auf entfernte Rechner ausweiten: Verbindungsarten und Voraussetzungen
5.1. Lokal und remote ändert sich die Verbindungsart
Ein CIM-Cmdlet ohne -CimSession verbindet sich ohne -ComputerName per COM mit dem lokalen WMI und erstellt bei Angabe von -ComputerName eine temporäre Sitzung über das WSMan-Protokoll (WinRM). Bei mehreren Vorgängen gegen denselben Computer ist das Anlegen und Wiederverwenden einer CIM-Sitzung leistungsfähiger.3
flowchart TB
accTitle: Wahl der CIM-Verbindungsart
accDescr: Ohne CimSession verbindet das Weglassen von ComputerName per COM mit lokalem WMI, die Angabe von ComputerName erstellt bei jeder Abfrage eine temporäre WSMan-Sitzung, das Wiederverwenden von New-CimSession ist bei mehreren Vorgängen gegen dasselbe Ziel leistungsfähiger, und für Ziele ohne WinRM gibt es die DCOM-Protokolloption
exec["Ohne CimSession ausführen"] --> q1{"Ist ComputerName angegeben?"}
q1 -->|Nein| local["COM-Verbindung zum lokalen WMI"]
q1 -->|Ja| q2{"Mehrere Vorgänge gegen dasselbe Ziel?"}
q2 -->|Einzeln| temp["Temporäre WSMan-Sitzung"]
q2 -->|Mehrere| sess["New-CimSession wiederverwenden"]
temp -.-> cost["Wird bei jeder Abfrage erstellt"]
nowinrm["Ziel ohne konfiguriertes WinRM"] -.-> dcom["DCOM-Protokolloption"]
Abbildung 8: Remoteabfragen nutzen standardmäßig WSMan; bei mehreren Vorgängen gegen dasselbe Ziel ist die Wiederverwendung einer CIM-Sitzung die etablierte Praxis.
5.2. WinRM, Firewall, Authentifizierung und Rechte vorbereiten
Die Voraussetzungen für Abfragen über WSMan/WinRM sind die folgenden. Bevor Sie Verbindungscode schreiben, prüfen Sie Dienst, Netzpfad, Authentifizierung und Rechte getrennt.
- WinRM muss auf dem Ziel konfiguriert sein.
winrm quickconfigerledigt alles auf einmal: Dienst auf automatischen Start setzen, HTTP-Listener anlegen (Standardport 5985) und eine Firewallausnahme eintragen.10 Für HTTPS (Standardport 5986) reicht das nicht: Sie brauchen ein Serverzertifikat und konfigurieren den HTTPS-Listener gesondert, etwa mitwinrm quickconfig -transport:https.10 - Die betreffenden Ports müssen in den Firewalls entlang des Pfads offen sein. Entwurf und Registrierung von Empfangsregeln in der Praxis entsprechen dem Artikel zu Windows-Firewall und Geschäftsanwendungen.
- Authentifizierung. In einer Domäne authentifiziert Kerberos gegenseitig. In einer Arbeitsgruppe steht Kerberos nicht zur Verfügung, daher kann eine Eintragung des Ziels in die
TrustedHosts-Liste des Clients nötig sein. Halten Sie diese Liste so klein wie möglich.10 - Rechte. In der Standardkonfiguration erfolgen entfernte WMI-Abfragen und -Vorgänge in der Regel mit einem Konto, das auf dem Ziel zur Administratorengruppe gehört. Sollen Standardbenutzer zugreifen, müssen Sie Zugriffsrechte sowohl in WinRM als auch im WMI-Namensraum konfigurieren.10
flowchart TB
accTitle: Prüfung der Voraussetzungen für Remoteabfragen
accDescr: Auf dem Ziel setzt winrm quickconfig den Dienst auf automatischen Start, legt einen HTTP-Listener an und trägt eine Firewallausnahme ein; ein HTTPS-Listener wird nach Bereitstellen eines Zertifikats gesondert konfiguriert, und in einer Arbeitsgruppe kann die Eintragung in TrustedHosts nötig sein
qc["winrm quickconfig"] --> svc["Dienst auf automatischen Start"]
qc --> lis["HTTP-Listener angelegt (5985)"]
qc --> fw["Firewallausnahme"]
lis ~~~ https["HTTPS-Listener (5986)"]
https -.-> cert["Zertifikat bereitstellen und gesondert konfigurieren"]
fw ~~~ wg["Arbeitsgruppenumgebung"]
wg -.-> th["Nur wo nötig eintragen"]
Abbildung 9: winrm quickconfig setzt die Standardkonfiguration in einem Schritt; HTTPS-Listener und Arbeitsgruppenauthentifizierung werden gesondert behandelt.
5.3. Dieselbe Gegenstelle: CIM-Sitzung wiederverwenden
# Für einen einzelnen Vorgang -ComputerName (jedes Mal eine temporäre Sitzung)
Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName Server01, Server02
# Bei wiederholten Abfragen eine CIM-Sitzung wiederverwenden
$session = New-CimSession -ComputerName Server01
Get-CimInstance -ClassName Win32_OperatingSystem -CimSession $session
Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType = 3" -CimSession $session
Remove-CimSession $session
5.4. DCOM erwägen, wo WinRM nicht konfiguriert werden kann
Für Ziele, die Sie über WSMan nicht erreichen, etwa ältere Maschinen ohne WinRM, können Sie das DCOM-Protokoll wählen.4
$dcom = New-CimSessionOption -Protocol Dcom
$session = New-CimSession -ComputerName OldServer -SessionOption $dcom
DCOM nutzt auch dynamische RPC-Ports, was den Entwurf über Firewalls hinweg erschwert. Für alles, was Sie jetzt bauen, ist WSMan als Vorgabe die sicherere Annahme.
Die Sitzungsbeispiele zeigen, wie man sich verbindet. Beim Einbau sichern Sie die Aufräumarbeit mit try / finally oder ähnlich, sodass Remove-CimSession auch erreicht wird, wenn eine Abfrage unterwegs scheitert. Die im DCOM-Beispiel erstellte Sitzung wird ebenso aufgehoben.
6. In C# einbauen: zwei APIs und der Umgang mit Typen und Datum
6.1. Die zwei APIs nach Zweck wählen
Es gibt zwei API-Linien für WMI aus C#. Beide sind nur unter Windows.
| System.Management | Microsoft.Management.Infrastructure (MI-API) | |
|---|---|---|
| Bezug | In .NET Framework enthalten. Im aktuellen .NET das NuGet-Paket System.Management5 | Das NuGet-Paket Microsoft.Management.Infrastructure6 |
| Einstiegsklasse | ManagementObjectSearcher (WQL übergeben und abfragen)5 |
CimSession (Create, dann QueryInstances / InvokeMethod / Subscribe)6 |
| Typsystem | ManagementObject / ManagementEventWatcher11 |
CimInstance / CimSession — dieselben Typen wie die CIM-Cmdlets3 |
| Remote | DCOM-basiert | WSMan-basiert (CIM-Sitzungen). Asynchrone Varianten (*Async) vorhanden6 |
| Wo es passt | Lokaler Informationsabruf. Bestehenden Code erhalten | Remoteabfragen und Überwachung einbauen. Entwürfe, die auch PowerShell nutzen |
6.2. System.Management: WQL übergeben und nach CIM-Typen lesen
Übergeben Sie WQL als Zeichenkette und nehmen Sie die Ergebnissammlung von Get() entgegen.5
// NuGet: System.Management (nur Windows)
using System.Management;
using var searcher = new ManagementObjectSearcher(
@"root\cimv2",
"SELECT DeviceID, FreeSpace, Size FROM Win32_LogicalDisk WHERE DriveType = 3");
foreach (ManagementObject disk in searcher.Get())
{
var freeGb = (ulong)disk["FreeSpace"] / 1024.0 / 1024.0 / 1024.0;
var sizeGb = (ulong)disk["Size"] / 1024.0 / 1024.0 / 1024.0;
Console.WriteLine($"{disk["DeviceID"]} frei {freeGb:F1} GB / gesamt {sizeGb:F1} GB");
}
Eigenschaften kommen über den Indexer als object zurück, daher prüfen Sie den CIM-Typ in der Klassendokumentation (hier sind FreeSpace und Size uint649) und casten entsprechend. Ein Cast nach int aus der Annahme heraus, ohne zu prüfen, ergibt InvalidCastException — das ist der klassische erste Stolperstein.
flowchart TB
accTitle: Eigenschaftsabruf und die Cast-Falle
accDescr: Eigenschaften von System.Management kommen über den Indexer als object zurück, daher muss der CIM-Typ in der Klassendokumentation geprüft werden, bevor gecastet wird; ein Cast in der Annahme, es sei int, ergibt InvalidCastException
idx["Über den Indexer abgerufen"] --> obj["Kommt als object zurück"]
obj --> chk["CIM-Typ in der Dokumentation prüfen"]
chk --> cast["Auf den richtigen Typ casten"]
obj -.-> wrong["Cast in der Annahme, es sei int"]
wrong -.-> ex["InvalidCastException"]
Abbildung 10: Eigenschaften kommen als object zurück, daher den CIM-Typ prüfen, bevor Sie casten.
6.3. MI-API: Mit denselben Typen wie PowerShell abfragen
CimSession behandelt lokal und remote gleich. Auflistung, Abfragen, Methodenaufrufe, Ereignisabonnement und asynchrone Varianten sind alle da.6
// NuGet: Microsoft.Management.Infrastructure (nur Windows)
using Microsoft.Management.Infrastructure;
// CimSession.Create(null) für lokal; Computernamen für remote
using CimSession session = CimSession.Create(null);
IEnumerable<CimInstance> disks = session.QueryInstances(
@"root\cimv2", "WQL",
"SELECT DeviceID, FreeSpace, Size FROM Win32_LogicalDisk WHERE DriveType = 3");
foreach (CimInstance disk in disks)
{
var deviceId = (string)disk.CimInstanceProperties["DeviceID"].Value;
var free = (ulong)disk.CimInstanceProperties["FreeSpace"].Value;
Console.WriteLine($"{deviceId} frei {free / 1024.0 / 1024 / 1024:F1} GB");
}
Weil Sie dieselbe CimInstance behandeln, die die CIM-Cmdlets von PowerShell zurückgeben, verbindet sich der Ablauf „in PowerShell ausprobieren, dann nach C# übertragen“ geradlinig. Wenn Sie die Kopplung von C# und PowerShell selbst entwerfen, siehe „PowerShell aus C# ausführen und die Ergebnisse als Objekte empfangen“.
flowchart TB
accTitle: In PowerShell ausprobieren und nach C# übertragen
accDescr: Weil PowerShell-CIM-Cmdlets und die C#-MI-API denselben CimInstance-Typ behandeln, verbindet sich der Ablauf, in PowerShell zu prototypen und dann nach C# zu übertragen, geradlinig
trial["In PowerShell prototypen"] --> gci["CIM-Cmdlets"]
impl["Eigentliche Umsetzung in C#"] --> mi["MI-API"]
gci --> ci["Derselbe CimInstance-Typ"]
mi --> ci
ci -.-> flow["Das Übertragen verbindet sich geradlinig"]
Abbildung 11: CIM-Cmdlets und MI-API behandeln denselben CimInstance-Typ, daher trägt ein Prototyp in die eigentliche Umsetzung.
6.4. DMTF-Daten nicht von Hand zerschneiden; der Umwandlungs-API übergeben
WMI-Daten liegen als Zeichenkette im DMTF-Format der CIM-Spezifikation yyyymmddHHMMSS.mmmmmm±UUU (der Schlusswert ist der Versatz zu UTC in Minuten; Beispiel 20260801100000.000000+540). Hören Sie auf, den Rohwert mit Zeichenkettenoperationen zu zerschneiden, und nutzen Sie eine Umwandlungs-API.
- C# (System.Management):
ManagementDateTimeConverterwandelt zwischen DMTF-Format undDateTime/TimeSpanin beide Richtungen.11 - CIM-APIs (Get-CimInstance / MI-API): Datumseigenschaften kommen bereits als
DateTimezurück, sodass Sie dem Problem gar nicht begegnen.(Get-CimInstance Win32_OperatingSystem).LastBootUpTimelässt sich direkt alsDateTimerechnen.
flowchart TB
accTitle: Umgang mit dem DMTF-Datumsformat
accDescr: WMI-Daten liegen als Zeichenkette im DMTF-Format; ein über System.Management gelesener Rohwert wird mit ManagementDateTimeConverter umgewandelt, eine CIM-API gibt bereits DateTime zurück, und die Zeichenkette wird nie selbst zerschnitten
dmtf["Zeichenkette im DMTF-Format"] --> q1{"Mit welcher API abgerufen?"}
q1 -->|System.Management| conv["ManagementDateTimeConverter"]
q1 -->|CIM-API| done["Bereits als DateTime zurückgegeben"]
conv --> dtv["Nach DateTime / TimeSpan umwandeln"]
cut["Zeichenkette selbst zerschneiden"] -.-> ng["Nicht tun"]
Abbildung 12: Die Umwandlung der DMTF-Zeichenkette der Umwandlungs-API überlassen; mit einer CIM-API das gelieferte DateTime direkt nutzen.
Der Code hier zeigt die Grundform jeder API. In einer echten Anwendung müssen Sie außerdem Abruffehler und nicht gesetzte Werte behandeln und Ergebnissammlungen, abgerufene Objekte und Sitzungen so freigeben, wie es die genutzte API verlangt.
7. Prozessstarts überwachen: Rechte, Abonnieren, Aufheben, erneutes Registrieren
Statt „Win32_Process in Abständen abzufragen und die Differenz zu betrachten“ nutzen Sie ein Ereignisabonnement. Für Prozessstarts ist das Abonnieren von Win32_ProcessStartTrace am einfachsten (eine Ereignisklasse des Kernel-Trace-Providers mit Eigenschaften wie ProcessName, ProcessID und ParentProcessID8).
7.1. Zuerst Ausführungsrechte und den Ort der Überwachung festlegen
Register-CimIndicationEvent registriert ein Abonnement über Klassennamen oder WQL-Ereignisabfrage, und der Skriptblock in -Action läuft bei jeder Ankunft.7 Das Abonnieren dieser Klasse erfordert Administratorrechte.7 Wer ein Ereignis empfangen darf, steuert der Sicherheitsdeskriptor der Ereignisklasse; ein Standardbenutzer erhält Zugriff verweigert.8
Abonnements der Familie Win32_ProcessStartTrace setzen Administratorrechte voraus.7 „Auf der Entwicklungsmaschine, als Administrator ausgeführt, lief es; in der Kundenumgebung als Standardbenutzer läuft die Überwachung nicht“ ist ein Klassiker neben dem Firewall-Hinweisdialog. Bauen Sie Überwachung in eine Geschäftsanwendung ein, die als Standardbenutzer läuft, trennen Sie den Überwachungsteil in einen Windows-Dienst (LocalSystem oder ähnlich) und verbinden Sie ihn mit der Anwendung über Interprozesskommunikation.
flowchart TB
accTitle: Überwachungsaufbau in Standardbenutzerumgebungen
accDescr: Ein Abonnement, das Administratorrechte voraussetzt, wird aus der als Standardbenutzer laufenden Anwendung herausgelöst, der Überwachungsteil wird in einen Windows-Dienst unter LocalSystem oder ähnlich getrennt, und beide werden über Interprozesskommunikation verbunden
svcm["Windows-Dienst für die Überwachung"] --> subm["Abonniert den Starttrace"]
svcm -.-> lsm["Läuft als LocalSystem oder ähnlich"]
appm["Die Anwendung selbst (Standardbenutzer)"] ---|Interprozesskommunikation| svcm
Abbildung 13: Ein Abonnement, das Administratorrechte braucht, auf die Dienstseite trennen und über Interprozesskommunikation mit der Anwendung verbinden.
7.2. In PowerShell abonnieren und am Ende der Überwachung aufheben
# In einer PowerShell-Sitzung mit Administratorrechten ausführen
$action = {
$name = $Event.SourceEventArgs.NewEvent.ProcessName
$id = $Event.SourceEventArgs.NewEvent.ProcessID
Write-Host "Prozess gestartet: $name (PID=$id)"
}
Register-CimIndicationEvent -ClassName Win32_ProcessStartTrace `
-SourceIdentifier ProcessStarted -Action $action
Das Abonnement ist an die PowerShell-Sitzung gebunden, die es registriert hat, und solange sie normal weiterläuft, läuft -Action bei jedem Prozessstart. Führen Sie den Aufhebungsbefehl nicht sofort hinterher in einem Rutsch aus: Dann ist das Abonnement weg, bevor die Überwachung beginnt.
Heben Sie auf, wenn die Überwachung endet.
# Wenn die Überwachung endet: das Abonnement aufheben
Unregister-Event -SourceIdentifier ProcessStarted
sequenceDiagram
accTitle: Ablauf eines Abonnements für Prozessstart-Ereignisse
accDescr: Eine PowerShell-Sitzung mit Administratorrechten registriert ein Abonnement mit Register-CimIndicationEvent, bei jedem Prozessstart kommt ein Ereignis und Action läuft, und das Abonnement wird mit Unregister-Event aufgehoben, wenn die Überwachung endet
participant ps as PowerShell-Sitzung
participant wmi as WMI
ps->>wmi: Abonnement mit Register-CimIndicationEvent registrieren
Note over ps: Mit Administratorrechten ausführen
wmi-->>ps: Bei jedem Prozessstart kommt ein Ereignis
ps->>ps: -Action ausführen
ps->>wmi: Mit Unregister-Event aufheben (am Ende der Überwachung)
Abbildung 14: Ein Abonnement ist an die registrierende Sitzung gebunden; aufheben, wenn die Überwachung endet.
7.3. Das generische Ereignis mit WITHIN ist Polling
Der andere Weg ist das generische Instanzerstellungsereignis (__InstanceCreationEvent), das die Erstellung von Instanzen einer Klasse überwacht. Hier pollt WMI im mit WITHIN angegebenen Intervall und macht die Differenz zu Ereignissen; den Ausgleich zwischen Erkennungslatenz und Last setzen Sie selbst.
flowchart TB
accTitle: Zwei Abonnementarten zur Erkennung von Prozessstarts
accDescr: Win32_ProcessStartTrace abonniert eine Ereignisklasse des Kernel-Trace-Providers, das generische __InstanceCreationEvent lässt WMI im mit WITHIN angegebenen Intervall pollen und die Differenz zu Ereignissen machen, sodass Sie den Ausgleich zwischen Erkennungslatenz und Last selbst setzen
goal["Erkennung von Prozessstarts"] --> t1["Win32_ProcessStartTrace"]
goal --> t2["__InstanceCreationEvent"]
t1 -.-> k1["Abonnieren eines Kernel-Trace"]
t2 -.-> w1["Pollt im WITHIN-Intervall"]
w1 -.-> tr["Ausgleich zwischen Intervall und Last"]
Abbildung 15: Entweder eine eigene Ereignisklasse abonnieren oder das generische Instanzerstellungsereignis mit Pollingintervall nutzen.
# Neue Win32_Process-Instanzen durch Polling im 5-Sekunden-Intervall überwachen
$query = "SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process'"
Register-CimIndicationEvent -Query $query -SourceIdentifier ProcPoll -Action {
Write-Host "Gestartet: $($Event.SourceEventArgs.NewEvent.TargetInstance.Name)"
}
7.4. In C# mit ManagementEventWatcher empfangen
In C# (System.Management) übernimmt ManagementEventWatcher dieselbe Rolle.11
using System.Management;
// In einem Prozess, der als Administrator läuft
var watcher = new ManagementEventWatcher(
new WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace"));
watcher.EventArrived += (_, e) =>
{
var name = (string)e.NewEvent["ProcessName"];
var pid = (uint)e.NewEvent["ProcessID"];
Console.WriteLine($"Prozess gestartet: {name} (PID={pid})");
};
watcher.Start();
// Am Ende der Überwachung watcher.Stop() und Dispose nicht vergessen
7.5. Dauerüberwachung: erneute Registrierung nach Abbruch mitentwerfen
Wenn Sie das in Dauerüberwachung einbauen, gehört die erneute Registrierung nach einem Abbruch des Abonnements (Neustart des Dienstes, Fehler) zum Entwurf. Die Entwurfslogik hinter „Zustand prüfen und anzeigen“, einschließlich Geräteüberwachung, behandelt „Best Practices zum Prüfen und Anzeigen des Zustands externer Geräte“.
stateDiagram-v2
accTitle: Lebenszyklus des Abonnements in der Dauerüberwachung
accDescr: In der Dauerüberwachung kann der abonnierte Zustand bei einem Dienstneustart oder einem Fehler abbrechen, daher muss der Entwurf das Erkennen des Abbruchs, die erneute Registrierung und die Rückkehr in den abonnierten Zustand enthalten
s1: Abonniert
s2: Abonnement abgebrochen
s3: Erneut registrieren
[*] --> s1
s1 --> s2: Dienstneustart oder Fehler
s2 --> s3
s3 --> s1
Abbildung 16: Dauerüberwachung muss den Entwurf enthalten, nach einem Abbruch erneut zu registrieren und in den abonnierten Zustand zurückzukehren.
8. Störungen eingrenzen: Leistung, Bitzahl und Repository
Wenn Sie sich nicht verbinden können, zurück zu Abschnitt 5.2; wenn nur das Abonnement verweigert wird, Abschnitt 7.1; für Cast und Datum Abschnitt 6.2 und 6.4. Hier die anderen häufigen Fälle: „langsam“, „falscher Wert“ und „Klasse nicht gefunden“.
8.1. Langsam: Menge, Häufigkeit und Sitzungen prüfen
Eine WMI-Abfrage ist Arbeit, bei der „der Provider die Werte an Ort und Stelle erzeugt“, und sie ist nicht kostenlos. Zwei klassische Anti-Muster:
SELECT *aus Gewohnheit. Jede Instanz vonWin32_Processmit jeder Eigenschaft aufzurufen, bläht die Arbeit des Providers und bei Remoteabfragen die Netzübertragung auf. Zeilen mit-Filterund Spalten mit-Propertyeingrenzen, und-KeyOnlynutzen, wenn Sie nur die Schlüssel für einen Folgevorgang brauchen. All das ist offiziell da, um „Objektgröße und Netzverkehr zu senken“.3- Polling in kurzen Abständen. Ein Entwurf wie „einmal pro Sekunde
Get-CimInstance Win32_Process“ gehört durch das Ereignisabonnement aus Kapitel 7 ersetzt. Auch wenn Sie die Polling-Form (WITHIN) wirklich brauchen, weiten Sie das Intervall auf das kleinste, das die Anforderung noch erfüllt.
Auch -ComputerName nacheinander gegen entfernte Ziele zu wiederholen, ist verschwenderisch. Bei jeder Abfrage entsteht eine temporäre Sitzung, daher mehrere Vorgänge auf die Wiederverwendung einer CIM-Sitzung umstellen.3
flowchart TB
accTitle: Leistungs-Anti-Muster und ihre Ersetzung
accDescr: SELECT-Sternchen aus Gewohnheit wird durch Eingrenzen von Zeilen und Spalten mit Filter und Property ersetzt und KeyOnly, wenn nur Schlüssel nötig sind; Polling in kurzen Abständen durch ein Ereignisabonnement; ComputerName nacheinander durch Wiederverwenden einer CIM-Sitzung
a1["SELECT * aus Gewohnheit"] --> f1["Mit Filter und Property eingrenzen"]
f1 -.-> f2["KeyOnly, wenn nur Schlüssel"]
a2["Polling in kurzen Abständen"] --> f3["Durch Ereignisabonnement ersetzen"]
a3["ComputerName nacheinander"] --> f4["CIM-Sitzung wiederverwenden"]
Abbildung 17: Eingrenzen von Zeilen, Spalten und Schlüsseln, die passende Überwachungsart und Sitzungswiederverwendung halten unnötige Last niedrig.
8.2. Falscher Wert: 32-Bit- und 64-Bit-Provider prüfen
Unter 64-Bit-Windows gibt es Provider in 32-Bit- und 64-Bit-Fassung, und standardmäßig antwortet die Fassung, die zur Bitzahl der aufrufenden Anwendung passt.12 Der Klassiker ist der Registrierungsprovider (StdRegProv) in root\default: von einer 32-Bit-Anwendung gelesen, kommen die Werte der Wow6432Node-Seite (32-Bit-Sicht).12 Wenn „der über WMI gelesene Registrierungswert von dem in regedit abweicht“, verdächtigen Sie das zuerst.
Brauchen Sie die andere Sicht, fordern Sie sie ausdrücklich an, indem Sie beim Verbinden __ProviderArchitecture im Kontext angeben (plus __RequiredArchitecture, wenn es verpflichtend sein soll).12 Das Gesamtbild des Bitzahl-Problems behandelt auch „Win32-APIs sicher aus C# aufrufen — Praxisleitfaden zu P/Invoke“.
flowchart TB
accTitle: Providerwahl in einer 64-Bit-Umgebung
accDescr: Standardmäßig antwortet der Provider, der zur Bitzahl der aufrufenden Anwendung passt, sodass eine Registrierungsabfrage von einer 32-Bit-Anwendung die Werte der Wow6432Node-Seite erhält; __ProviderArchitecture erlaubt, die andere Sicht ausdrücklich anzufordern
q1{"Welche Bitzahl hat der Aufrufer?"} -->|32-Bit| p32["Der 32-Bit-Provider antwortet"]
q1 -->|64-Bit| p64["Der 64-Bit-Provider antwortet"]
p32 -.-> wow["Die Registrierungswerte kommen von Wow6432Node"]
ctx["__ProviderArchitecture angeben"] -.-> ov["Die andere Sicht ausdrücklich anfordern"]
Abbildung 18: Standardmäßig antwortet die zur Bitzahl des Aufrufers passende Seite, daher liest eine 32-Bit-Anwendung die Wow6432Node-Seite.
8.3. Klasse nicht gefunden: das Repository prüfen, dann reparieren
WMI-Klassendefinitionen liegen im Repository (keine einzelne Datei: die Dateien im Ordner Repository funktionieren als Datenbank13). Wird es inkonsistent, erscheinen Fehler wie „eine Klasse, die existieren sollte, wird nicht gefunden“ oder „ungültiger Namensraum“, obwohl sich auf Anwendungsseite nichts geändert hat.
Zum Eingrenzen und Reparieren dient winmgmt.exe.13
rem Konsistenzprüfung (Ergebnis inconsistent bedeutet eine Inkonsistenz)
winmgmt /verifyrepository
rem Konsistenzprüfung plus Neuaufbau bei Inkonsistenz (lesbarer Inhalt wird übernommen)
winmgmt /salvagerepository
Was Sie vermeiden müssen: Löschen oder Initialisieren des Repositorys nicht als ersten Schritt. Fehler, die über WMI auftauchen, können anderswo im Betriebssystem liegen, und Microsoft sagt ausdrücklich, dass das Löschen des Repositorys als erste Maßnahme „zu Schäden am System oder an installierten Anwendungen führen kann“.13 Die Reihenfolge halten: mit /verifyrepository prüfen, dann mit /salvagerepository reparieren.
flowchart TB
accTitle: Eingrenzung einer Inkonsistenz im WMI-Repository
accDescr: Bei Fehlern wie nicht gefundener Klasse die Konsistenz mit winmgmt verifyrepository prüfen, bei Inkonsistenz mit salvagerepository neu aufbauen und Löschen oder Initialisieren des Repositorys nie als ersten Schritt
sym["Fehler wie Klasse nicht gefunden"] --> verify["winmgmt /verifyrepository"]
verify --> q1{"Ist das Ergebnis inconsistent?"}
q1 -->|Ja| salvage["winmgmt /salvagerepository"]
q1 -->|Nein| other["Ursache anderswo im Betriebssystem vermuten"]
salvage -.-> merge["Lesbarer Inhalt wird übernommen"]
del["Löschen oder Initialisieren des Repositorys"] -.-> ng["Nicht der erste Schritt"]
Abbildung 19: Zuerst prüfen, dann salvagen; Löschen nicht als ersten Schritt.
9. Zusammenfassung: Von der Abfrage zu Überwachung und Betrieb
WMI/CIM ist der gemeinsame Einstieg, um Windows-Verwaltungsinformationen übergreifend abzufragen. Es ist kein Werkzeug, um alles in WMI zu zwingen, einschließlich Arbeit, die eine eigene API schon deckt.
| Phase des Einbaus | Was zu prüfen ist |
|---|---|
| Das Werkzeug wählen | Eigenen Mechanismus für Einstellungen, hochfrequente Leistungsüberwachung und einmalige OS-Vorgänge bevorzugen; WMI/CIM für Informationsabruf und Remoteabfragen |
| In PowerShell ausprobieren | Auch für 5.1 mit den CIM-Cmdlets schreiben. Eine Klasse in root/CIMV2 wählen und Zeilen, Spalten und Schlüssel eingrenzen |
| Auf entfernte Rechner ausweiten | WSMan-/WinRM-Verbindungsvoraussetzungen herstellen und eine Sitzung für mehrere Vorgänge wiederverwenden. Die DCOM-Option für Ziele erwägen, die sie brauchen |
| Nach C# übertragen | Zwischen System.Management für lokale Abfragen und der MI-API für Remoteabfragen und Überwachung wählen. Umgang mit Typen und Datum prüfen |
| Zur Dauerüberwachung machen | Die Rechte von Win32_ProcessStartTrace prüfen und Abonnieren, Aufheben und erneutes Registrieren nach einem Abbruch als einen durchgehenden Ablauf entwerfen |
| Eine Störung untersuchen | Polling in kurzen Abständen, Bitzahl des Providers und Konsistenz des Repositorys eingrenzen. Löschen nicht als erste Maßnahme |
Wenn Sie CIM-Standard und WMI-Implementierung, Abfrage und Ereignisabonnement sowie Verbindung und Zugriffsrechte getrennt denken, wird klar, welches Werkzeug zu wählen und was zu prüfen ist. Holen Sie die benötigten Informationen zuerst in PowerShell und tragen Sie das Ergebnis in die C#-Umsetzung und den Betriebsentwurf.
Verwandte Artikel
- PowerShell aus C# ausführen und die Ergebnisse als Objekte empfangen
- Praktische PowerShell-Befehlssammlung — Kleine Helfer für die tägliche Arbeit erweitern
- Die Unterschiede zwischen Windows PowerShell 5.1 und PowerShell 7 — Praxisleitfaden zur Migration interner Skripte
- Best Practices zum Prüfen und Anzeigen des Zustands externer Geräte - Design jenseits von nur „verbunden“
- Win32-APIs sicher aus C# aufrufen — Praxisleitfaden zu P/Invoke (DllImport / LibraryImport / CsWin32)
- Was ist das TPM in Windows? — Eine bebilderte Anleitung zum „Tresor, der Schlüssel niemals herausgibt“, und zum Measured Boot
Verwandte Beratungsleistungen
Die KomuraSoft LLC übernimmt den Einbau von Hardwareinformationsabruf, Prozessüberwachung und Remote-PC-Abfragen mittels WMI/CIM in Geschäftsanwendungen, die Migration von auf Get-WmiObject basierenden internen Skripten zu den CIM-Cmdlets sowie die Ursachenuntersuchung von Fällen wie „auf der Entwicklungsmaschine funktioniert es, beim Kunden erscheint ein Berechtigungsfehler“. Von der Erprobung in PowerShell bis zur vollständigen Umsetzung in C# begleiten wir Sie durchgehend.
- Windows-Anwendungsentwicklung
- Fehleruntersuchung und Ursachenanalyse
- Technische Beratung und Design-Review
- Kontakt
Referenzlinks
-
Microsoft Learn, About WMI. Dazu, dass WMI Microsofts Implementierung von WBEM ist (einer Brancheninitiative, die Standardtechnologien für den Zugriff auf Verwaltungsinformationen in Unternehmensumgebungen entwickelt), dass zur Darstellung von Verwaltungsobjekten der Branchenstandard CIM (Common Information Model) verwendet wird, der vom DMTF (Distributed Management Task Force) entwickelt und gepflegt wird, dass die Nachfolgeversion MI (Windows Management Infrastructure) vollständig mit dem klassischen WMI kompatibel ist, sowie dazu, dass entfernte WMI-Verbindungen über DCOM erfolgen, mit dem auf WS-Management basierenden WinRM als Alternative. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Differences between Windows PowerShell 5.1 and PowerShell 7.x. Dazu, dass die WMI-v1-Cmdlets (Register-WmiEvent / Set-WmiInstance / Invoke-WmiMethod / Get-WmiObject / Remove-WmiObject) aus PowerShell entfernt wurden, sowie dazu, dass die Cmdlets des Moduls CimCmdlets (WMI v2) dieselbe Funktionalität mit neuen Funktionen und überarbeiteter Syntax bereitstellen. ↩ ↩2 ↩3
-
Microsoft Learn, Get-CimInstance (CimCmdlets). Dazu, dass ohne Angabe von ComputerName oder CimSession eine COM-Sitzung zum lokalen WMI aufgebaut wird und bei Angabe von -ComputerName eine temporäre Sitzung über das WsMan-Protokoll erstellt wird; dazu, dass bei mehreren Vorgängen gegen denselben Computer eine Verbindung über eine CIM-Sitzung aus Leistungsgründen empfohlen wird; dazu, dass -Filter eine WQL-/CQL-WHERE-Klausel ohne das Schlüsselwort WHERE ist; dazu, dass -Property und -KeyOnly die Objektgröße und den Netzwerkverkehr reduzieren können; dazu, dass der Standardnamensraum root/CIMV2 und die Standardabfragesprache (-QueryDialect) WQL ist; dazu, dass die Ausgabe vom Typ Microsoft.Management.Infrastructure.CimInstance ist; zu einem Beispiel des Aufrufs von GetOwner in Kombination mit Invoke-CimMethod; sowie dazu, dass das Cmdlet ausschließlich unter Windows verfügbar ist. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10
-
Microsoft Learn, New-CimSessionOption (CimCmdlets). Dazu, dass CIM-Sitzungsoptionen zwei Parametersätze besitzen, für WsMan und für DCOM; dazu, dass -Protocol Dcom / Default / Wsman akzeptiert; zu einem Beispiel, bei dem eine mit New-CimSessionOption -Protocol Dcom erstellte Option an -SessionOption von New-CimSession übergeben wird, um eine DCOM-CIM-Sitzung zu erstellen; sowie dazu, dass die standardmäßige Impersonation-Ebene einer DCOM-Sitzung Impersonate ist. ↩ ↩2
-
Microsoft Learn, ManagementObjectSearcher Class (System.Management). Dazu, dass dies die gängigste Einstiegsklasse für den Abruf von Verwaltungsinformationen ist, die eine Sammlung von Verwaltungsobjekten anhand einer angegebenen WQL-Abfrage abruft; dazu, dass sie eine ObjectQuery und einen ManagementScope (den WMI-Namensraum) entgegennimmt und über Get() eine ManagementObjectCollection zurückgibt; sowie dazu, dass System.Management.dll als NuGet-Paket System.Management bereitgestellt wird. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, CimSession Class (Microsoft.Management.Infrastructure). Dazu, dass Microsoft.Management.Infrastructure.dll als NuGet-Paket Microsoft.Management.Infrastructure bereitgestellt wird; zur Erstellung einer Sitzung über Create(computerName); zur Ausführung einer Abfrage über QueryInstances(namespace, queryDialect, query); sowie dazu, dass EnumerateInstances / GetInstance / InvokeMethod / Subscribe jeweils mit asynchronen Varianten (*Async) bereitgestellt werden und die Klasse IDisposable implementiert. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Register-CimIndicationEvent (CimCmdlets). Dazu, dass eine Indikation (ein Ereignis) über Klassennamen oder Abfrageausdruck abonniert und das Abonnement mit -SourceIdentifier benannt wird; zu einem Beispiel des Abonnierens von Win32_ProcessStartTrace mit dem Hinweis, dass dafür PowerShell als Administrator ausgeführt werden muss; zu einem Beispiel, bei dem im Skriptblock von -Action über $Event.SourceEventArgs.NewEvent auf ProcessName / ProcessId zugegriffen wird; dazu, dass bei Angabe von -ComputerName eine temporäre WsMan-Sitzung und ohne Angabe eine lokale COM-Verbindung verwendet wird; sowie dazu, dass Unregister-Event zum Aufheben eines Abonnements dient. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Win32_ProcessStartTrace class. Dazu, dass dies eine Ereignisklasse ist, die den Start eines neuen Prozesses anzeigt, mit Eigenschaften wie ProcessName / ProcessID / ParentProcessID / SessionID / Sid; dazu, dass die Eigenschaft SECURITY_DESCRIPTOR der Deskriptor ist, anhand dessen der Ereignisprovider festlegt, welche Benutzer das Ereignis empfangen dürfen; sowie dazu, dass der Namensraum Root\CIMV2 ist und die Klasse vom Kernel-Trace-Provider (Krnlprov.dll) bereitgestellt wird. ↩ ↩2 ↩3
-
Microsoft Learn, Win32_LogicalDisk class. Dazu, dass Win32_LogicalDisk eine von CIM_LogicalDisk abgeleitete Klasse ist, die ein lokales Speichergerät darstellt; zu den Werten von DriveType (2 = Wechseldatenträger, 3 = lokales Laufwerk, 4 = Netzlaufwerk, 5 = CD usw.); dazu, dass FreeSpace / Size Bytewerte vom Typ uint64 sind; dazu, dass DeviceID der Schlüssel ist; sowie zu Beispielabfragen in VBScript / C#, die nach DriveType = 3 filtern. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Installation and configuration for Windows Remote Management. Dazu, dass standardmäßig kein WinRM-Listener konfiguriert ist und WS-Management-Nachrichten daher nicht gesendet oder empfangen werden können; dazu, dass winrm quickconfig den Dienst auf automatischen Start setzt, einen HTTP-/HTTPS-Listener konfiguriert und eine Firewallausnahme einträgt; dazu, dass die Standardports von WinRM 2.0 HTTP 5985 / HTTPS 5986 sind; dazu, dass TrustedHosts so eng wie möglich zu setzen ist, wenn eine gegenseitige Authentifizierung (Kerberos) nicht zustande kommt, etwa in einer Arbeitsgruppe; sowie zum standardmäßigen Sicherheitsdeskriptor (RootSDDL), der den Remotezugriff auf den Listener steuert, und zur zusätzlichen Konfiguration, die nötig ist, um Nicht-Administratoren die Nutzung von WMI-Plug-ins zu erlauben. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, System.Management Namespace. Dazu, dass dies der Namensraum ist, der Abfragen an die WMI-Infrastruktur über die ManagementObjectSearcher-Klassenfamilie stellt und Ereignisabonnements über ManagementEventWatcher abwickelt; dazu, dass WqlEventQuery eine Ereignisabfrage im WQL-Format darstellt; sowie dazu, dass ManagementDateTimeConverter Methoden zur Umwandlung zwischen DMTF-Datums-/Zeitangaben und Zeitintervallen sowie DateTime / TimeSpan der CLR bereitstellt. ↩ ↩2 ↩3
-
Microsoft Learn, Requesting WMI Data on a 64-bit Platform. Dazu, dass bei Providern, die sowohl in 32-Bit- als auch in 64-Bit-Version existieren, standardmäßig der 32-Bit-Provider 32-Bit-Anwendungen (einschließlich Skripten) und der 64-Bit-Provider 64-Bit-Anwendungen bedient; dazu, dass sich die jeweils andere Version über den Kontext-Wert __ProviderArchitecture (32 oder 64) sowie __RequiredArchitecture explizit anfordern beziehungsweise erzwingen lässt (wobei beim Erzwingen einer nicht vorhandenen Version WBEM_E_PROVIDER_LOAD_FAILURE auftritt); sowie zum Beispiel des Registrierungsproviders, bei dem ein 32-Bit-Client Daten von der Seite HKLM\SOFTWARE\Wow6432Node erhält. ↩ ↩2 ↩3
-
Microsoft Learn, winmgmt. Dazu, dass /verifyrepository von winmgmt.exe eine Konsistenzprüfung des WMI-Repositorys durchführt; dazu, dass /salvagerepository eine Konsistenzprüfung durchführt und bei erkannter Inkonsistenz das Repository neu aufbaut, wobei lesbare Inhalte übernommen werden; dazu, dass /resetrepository das Repository auf den Zustand der ursprünglichen Betriebssysteminstallation zurücksetzt; dazu, dass das Repository als Datenbank aus den Dateien im Repository-Ordner funktioniert; sowie dazu, dass über WMI auftretende Fehler mitunter andere Ursachen im Betriebssystem haben, weshalb das Löschen des Repositorys als erste Maßnahme vermieden werden sollte, da dies zu Schäden am System oder an installierten Anwendungen führen kann. ↩ ↩2 ↩3
Verwandte Artikel
Aktuelle Artikel mit denselben Schlagwörtern führen zu verwandten Themen weiter.
Warum Argumente zerbrechen — Die Regeln der Windows-Kommandozeilenargumente
Windows übergibt CreateProcess eine einzige Zeichenfolge, die der Empfänger zerlegt. Behandelt die Regeln von CommandLineToArgvW, CRT und...
Ende der Wartung von Windows-Druckertreibern — Wie Geschäftsanwendungen Bericht- und Etikettendruck vorbereiten
Microsoft stellt v3/v4-Druckertreiber schrittweise ein. Was Windows protected print mode entfernt und wie Geschäftsanwendungen Bericht- u...
Praktische Best Practices für Multithreading: .NET-Edition — Was Sie entscheiden sollten, bevor Sie weitere Threads hinzufügen
Eine praxisnahe Übersicht der Entwurfsregeln, die verhindern, dass Multithreading-Code in .NET/C# gelegentlich abstürzt oder hängen bleib...
Mehrfachstarts einer Windows-App verhindern — Benannte Mutexe und das Aktivieren des vorhandenen Fensters beim zweiten Start
Dieser Artikel ordnet die klassische Anforderung für Business-Windows-Apps – „dieselbe App darf nicht zweimal starten“ – rund um einen be...
PowerShell aus C# (CSharp) ausführen und die Ergebnisse als Objekte empfangen
Wie man PowerShell aus C# startet und das Ergebnis nicht als Zeichenkette, sondern als PSObject empfängt – ein praxisorientierter Überbli...
Verwandte Themen
Diese Seiten ordnen den Artikel in einen größeren Leistungs- und Entscheidungskontext ein.
Technische Windows-Themen
Portal zu Windows-Entwicklung, Fehleranalyse und der Nutzung bestehender Assets.
Leistungen zu diesem Thema
Dieser Artikel ist direkt mit den folgenden Leistungen verbunden.
Windows-App-Entwicklung
Geschäftsanwendungen, Geräteintegration und Kommunikationstools von den Anforderungen bis zur Umsetzung.
Häufige Fragen
Fragen, die in Beratungen zu diesem Artikelthema häufig gestellt werden.
- Was ist der Unterschied zwischen WMI und CIM?
- CIM ist das vom DMTF (Distributed Management Task Force) festgelegte und gepflegte Branchenstandardmodell zur Darstellung von Verwaltungsobjekten wie Systemen und Geräten. WMI ist Microsofts Implementierung von WBEM, einer Initiative, die diesen Standard nutzt, und ist fest in Windows integriert. Mit anderen Worten: CIM ist die Spezifikation, WMI die Implementierung unter Windows. PowerShells Get-CimInstance und C#s Microsoft.Management.Infrastructure tragen die Bezeichnung CIM, weil es sich um APIs handelt, die diesem Standard folgen; die Verbindung geht dabei zur selben WMI-Grundlage. Für die tägliche Entwicklung reicht das Verständnis: WMI-Klassen (Win32_* usw.) werden über CIM-basierte APIs abgefragt.
- Kann ich Get-WmiObject nicht mehr verwenden?
- Unter Windows PowerShell 5.1 funktioniert es weiterhin, aber ab PowerShell 6 (einschließlich der aktuellen PowerShell 7) sind die WMI-v1-Cmdlets Get-WmiObject, Invoke-WmiMethod, Register-WmiEvent, Set-WmiInstance und Remove-WmiObject entfernt und lassen sich nicht mehr ausführen. Dieselbe Funktionalität stellt das Modul CimCmdlets bereit (Get-CimInstance / Invoke-CimMethod / Register-CimIndicationEvent usw.). Neue Skripte sollten daher auch dann mit den CIM-Cmdlets geschrieben werden, wenn sie unter 5.1 laufen sollen. So muss bei einer späteren Migration zu PowerShell 7 der WMI-Teil nicht neu geschrieben werden.
- Sollte ich in C# System.Management oder Microsoft.Management.Infrastructure verwenden, um auf WMI zuzugreifen?
- Beide sind nur unter Windows verfügbar und werden im aktuellen .NET als NuGet-Paket eingebunden. System.Management ist die klassische API, die sich allein durch Übergabe von WQL an einen ManagementObjectSearcher nutzen lässt, und reicht aus, wenn hauptsächlich lokale Informationen abgerufen werden. Es enthält außerdem ManagementDateTimeConverter zur Konvertierung von DMTF-Datumsangaben. Microsoft.Management.Infrastructure (die MI-API) dagegen teilt sich dasselbe Typsystem (CimSession / CimInstance) mit den CIM-Cmdlets von PowerShell und deckt Remoteabfragen über WSMan, asynchrone Methodenvarianten und Ereignisabonnements (Subscribe) einheitlich ab. Wer Remoteabfragen und Überwachung fest in eine Anwendung einbauen will, trifft mit der MI-API die sinnvollere Wahl.
- Get-CimInstance verbindet sich nicht mit einem entfernten PC. Was sollte ich prüfen?
- Prüfen Sie zuerst, ob auf dem Zielrechner WinRM konfiguriert ist. Ein CIM-Vorgang mit -ComputerName erstellt eine temporäre Sitzung über das WSMan-Protokoll (WinRM) und setzt daher voraus, dass der WinRM-Dienst und ein Listener auf dem Ziel laufen. winrm quickconfig führt die Standardkonfiguration aus (Dienst automatisch starten, Listener erstellen, Firewallausnahme eintragen). Die Standardports sind 5985 für HTTP und 5986 für HTTPS, prüfen Sie also auch die Firewalls entlang des Netzwerkpfads. In einer Arbeitsgruppenumgebung steht keine gegenseitige Authentifizierung über Kerberos zur Verfügung, sodass mitunter eine Eintragung des Ziels in die TrustedHosts-Liste des Clients nötig ist. Für ein Ziel, bei dem WinRM unter keinen Umständen konfiguriert werden kann, lässt sich stattdessen über DCOM verbinden, mit einer über New-CimSessionOption -Protocol Dcom erstellten Option.
- Warum wird ein WMI-Datum in einem Format wie 20260801100000.000000+540 zurückgegeben?
- WMI-Datumswerte werden als Zeichenkette im DMTF-Format der CIM-Spezifikation gespeichert (yyyymmddHHMMSS.mmmmmm±UUU, wobei der abschließende Wert den Versatz gegenüber UTC in Minuten angibt). Wird der Rohwert mit dem alten Get-WmiObject oder mit System.Management gelesen, erhält man genau diese Zeichenkette. In C# (System.Management) stellt ManagementDateTimeConverter Methoden zur Umwandlung zwischen dem DMTF-Format und DateTime / TimeSpan bereit; verwenden Sie diese, statt die Zeichenkette selbst zu zerlegen. Bei Abruf über eine CIM-basierte API wie Get-CimInstance oder die MI-API kommen Datumseigenschaften dagegen bereits als DateTime zurück, sodass dieses Problem dort von vornherein nicht auftritt.
Autorenprofil
Profilseite des Artikelautors.
Go Komura
Geschäftsführer von KomuraSoft LLC
Spezialisiert auf Windows-Softwareentwicklung, technische Beratung und Fehleranalyse, insbesondere bei bestehenden Systemen und schwer reproduzierbaren Störungen.