PowerShell WMI: Automatisiere Windows-Aufgaben

Windows-Verwaltungsinstrumentation (WMI) existiert schon seit langem in Windows. Viele IT-Profis haben WMI entweder direkt verwendet oder Tools verwendet, die Informationen aus WMI lesen. Wussten Sie, dass PowerShell WMI-Cmdlets bereits integriert sind?

WMI ist der De-facto-Ort, um Informationen über einen Windows-Rechner zu sammeln und verschiedene Dienste innerhalb von Windows zu manipulieren. Aufgrund der umfangreichen Informationen von WMI können Sie mit PowerShell WMI arbeiten. Die Verwendung von PowerShell zur Abfrage von WMI ermöglicht es Ihnen, Tausende von Aufgaben auf Windows-Computern zu automatisieren.

Zum Glück hatte eines der ersten Systeme in Windows, für das PowerShell Befehle hatte, WMI. Da Sie native PowerShell WMI-Cmdlets haben, konnte ein IT-Administrator die leicht verständliche Verb/Nomen-Syntax von PowerShell nutzen, um mit WMI zu interagieren, und, wie Sie sehen werden, können Power-User auch WMI-Ereignisse und Klassen direkt durch die Verwendung von Standard-PowerShell-Befehlen aufrufen.

PowerShell WMI-Cmdlets vs. CIM

Es gibt zwei „Sets“ von Befehlen, wenn es darum geht, WMI in PowerShell zu verwenden. Einige Leute beziehen sich auf diese „Sets“ als die „alte“ Art der Interaktion mit WMI und die CIM-Cmdlets. Beim Abfragen von Informationen aus WMI liefern beide die gleichen Informationen, gehen jedoch ein wenig anders damit um. Die „alte“ Methode zum Lesen von Informationen aus WMI besteht darin, den Befehl Get-WmiObject zu verwenden. Andere WMI-Cmdlets umfassen Invoke-WmiMethod, Register-WMIEvent usw., aber wir werden diese in unserem Artikel nicht behandeln.

Das PowerShell WMI-Cmdlet Get-WmiObject funktioniert, hat aber einen ernsthaften Nachteil. Beim Abfragen von entfernten Computern verlässt es sich auf DCOM, und DCOM war historisch betrachtet ein Angriffsvektor für böswillige Akteure. DCOM wird normalerweise von verschiedenen Firewalls blockiert. Da dies der „alte“ Weg ist, werden wir uns nicht weiter mit dieser Methode befassen. Stattdessen konzentrieren wir uns auf die CIM-Cmdlets: hauptsächlich Get-CimInstance.

DCOM Component Services

Der große Unterschied zwischen Get-WmiObject und Get-CimInstance besteht darin, dass Get-CimInstance anstelle von DCOM zum Zugriff auf entfernte Computer das WSMAN-Protokoll verwendet, das auch für das vertraute PowerShell Remoting-Feature verwendet wird.

PowerShell CIM-Cmdlets

Sagen wir, Sie möchten einige Informationen zur Version von Windows auf einem entfernten Computer abrufen. In diesem Fall möchte ich Informationen von einem Computer namens DC sehen. Sie können dies tun, indem Sie die WMI-Klasse angeben, die die Informationen enthält, und den Computernamen, den ich abfragen möchte.

Sie können unten sehen, dass Get-CimInstance standardmäßig nicht alle Attribute innerhalb der Klasse anzeigt. Daher musste ich die Ausgabe an das Select-Object-Cmdlet weiterleiten, um alle Eigenschaften zurückzugeben.

PS> Get-CimInstance -ClassName Win32_OperatingSystem -ComputerName DC | Select *
Status                                    : OK
Name                                      : Microsoft Windows 10 Pro|C:\WINDOWS|\Device\Harddisk0\Partition2
FreePhysicalMemory                        : 1802336
FreeSpaceInPagingFiles                    : 800308
FreeVirtualMemory                         : 1472916
Caption                                   : Microsoft Windows 2016
Description                               :
InstallDate                               : 7/5/2018 6:04:09 PM
CreationClassName                         : Win32_OperatingSystem
CSCreationClassName                       : Win32_ComputerSystem
--snip-

Nicht nur können Sie Informationen über Eigenschaften sammeln, sondern Sie können auch WMI/CIM-Methoden auf Klassen aufrufen. Ein gutes Beispiel hierfür ist das Stoppen eines Prozesses auf einem Remote-Computer. Natürlich gibt es keine Möglichkeit, dies über den Stop-Process-Befehl in PowerShell zu tun. Es gibt jedoch einen Weg über die WMI-Abfrage. Um Remote-Prozesse zu beenden, müssen wir zunächst herausfinden, welchen Prozess wir beenden möchten. Wir können alle laufenden Prozesse auf einem Remote-Computer aufzählen, indem wir uns die Klasse Win32_Process ansehen.

PS> Get-CimInstance -ClassName CIM_Process -ComputerName DC

ProcessId Name                                      HandleCount WorkingSetSize VirtualSize   PSComputerName
--------- ----                                      ----------- -------------- -----------   --------------
0         System Idle Process                       0           4096           65536         DC
4         System                                    631         212992         3465216       DC
232       smss.exe                                  52          823296         4325376       DC
328       csrss.exe                                 258   om      3346432        49483776      DC
392       csrss.exe                                 87          2789376        44507136      DC
400       wininit.exe                               80          3072000        2199065096192 DC
428       winlogon.exe                              119         4431872        2199079510016 DC

Wenn Sie herausgefunden haben, welchen Prozess Sie beenden möchten, können Sie den Namen an die Terminate()-Methode der Klasse Win32_Process übergeben. Dazu müssen Sie eine Instanz des zu beendenden Prozesses erfassen.

Beachten Sie unten, dass ich den Filter-Parameter verwende, um sicherzustellen, dass ich nur den ccmexec.exe-Prozess erhalte. Dies ist wichtig!

Nachdem Sie die Instanz erfasst haben, können Sie dann die Terminate()-Methode aufrufen, um den Prozess mithilfe des Invoke-CimMethod-Befehls wie unten gezeigt zu beenden.

PS> $instance = Get-CimInstance -ClassName CIM_Process -ComputerName DC -Filter 'Name = "ccmexec.exe"'
PS> $instance

ProcessId Name        HandleCount WorkingSetSize VirtualSize PSComputerName
--------- ----        ----------- -------------- ----------- --------------
3528      CcmExec.exe 878         34246656       158261248   DC


PS> Invoke-CimMethod -InputObject $instance -MethodName Terminate

ReturnValue PSComputerName
----------- --------------
          0 DC

Zusammenfassung

Wenn Sie mehr über die Verwendung von WMI in PowerShell erfahren möchten und insbesondere den hier nicht behandelten PowerShell-WMI-Cmdlet Get-WmiObject, empfehle ich Ihnen, Get-WmiObject: Abfragen von WMI auf lokalen und entfernten Computern zu lesen, wo ich tiefer in WMI eingehe und das Get-WmiObject-Cmdlet verwende.

Für eine vollständige Aufschlüsselung aller CIM-Cmdlets und deren Funktionsweise in PowerShell verweisen Sie bitte auf den Artikel Introduction to CIM Cmdlets auf Technet. Dort finden Sie alle verschiedenen CIM-Cmdlets und wie sie in Ihren Skripten verwendet werden können.

Source:
https://adamtheautomator.com/powershell-wmi/