PowerShell WMI: Automatiseer Windows Taken

Windows Management Instrumentation (WMI) bestaat al lange tijd in Windows. Veel IT-professionals hebben WMI rechtstreeks gebruikt of hebben tools gebruikt die informatie uit WMI lezen. Wist je dat de PowerShell WMI-cmdlets ingebouwd zijn?

WMI is de facto de plaats om informatie te verzamelen over een Windows-machine en verschillende services binnen Windows te manipuleren. Dankzij de uitgebreide informatie van WMI kun je via PowerShell WMI gebruiken. Het gebruik van PowerShell om WMI te bevragen stelt je in staat om duizenden taken op Windows-computers te automatiseren.

Gelukkig was een van de eerste systemen in Windows waarvoor PowerShell commando’s had WMI. Omdat je native PowerShell WMI-cmdlets hebt, betekent dit dat een IT-beheerder de eenvoudig te begrijpen werkwoord/zelfstandig naamwoord-syntaxis van PowerShell kon benutten om met WMI te communiceren en, zoals je zult zien, kunnen gevorderde gebruikers ook WMI-gebeurtenissen en klassen rechtstreeks oproepen door gewoon standaard PowerShell-commando’s te gebruiken.

PowerShell WMI-cmdlets vs. CIM

Er zijn twee “sets” van commando’s als het gaat om het gebruik van WMI in PowerShell. Sommige mensen verwijzen naar deze “sets” als de “oude” manier om met WMI te communiceren en de CIM-cmdlets. Bij het opvragen van informatie uit WMI geven beide dezelfde informatie terug, maar benaderen deze iets anders. De “oude” manier om informatie uit WMI te lezen is door het gebruik van het Get-WmiObject-commando. Andere WMI-cmdlets zijn onder andere Invoke-WmiMethod, Register-WMIEvent enzovoort, maar we zullen deze niet behandelen in ons artikel.

De PowerShell WMI-opdracht Get-WmiObject werkt, maar heeft een serieus nadeel. Bij het bevragen van externe computers vertrouwt het op DCOM en DCOM is historisch gezien een aanvalvector geweest voor slechte actoren. DCOM wordt meestal geblokkeerd door verschillende firewalls. Omdat dit de “oude” manier is, gaan we niet in op deze methode. In plaats daarvan zullen we ons richten op de CIM-opdrachten: primair, Get-CimInstance.

DCOM Component Services

Het grote verschil tussen Get-WmiObject en Get-CimInstance is dat Get-CimInstance in plaats van DCOM te gebruiken om toegang te krijgen tot externe computers, het WSMAN-protocol gebruikt, dat het transport is voor de bekende PowerShell remoting-functie.

PowerShell CIM-opdrachten

Stel dat je wat informatie wilt terugkrijgen over de versie van Windows op een externe computer. In dit geval wil ik wat informatie zien van een computer met de naam DC. Dit kun je doen door de WMI-klasse op te geven die de informatie bevat en de computernaam die ik wil bevragen.

Je kunt hieronder zien dat aangezien Get-CimInstance standaard niet alle attributen binnen de klasse weergeeft, ik de uitvoer heb moeten doorsturen naar de Select-Object-opdracht om alle eigenschappen terug te krijgen.

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-

Niet alleen kun je informatie verzamelen via eigenschappen, maar je kunt ook WMI/CIM-methoden aanroepen op klassen. Een goed voorbeeld hiervan is het stoppen van een proces op een externe computer. Ingebouwd is er geen manier om dit te doen via het Stop-Process-commando in PowerShell. Er is echter wel een manier via een WMI-query. Om externe processen te beëindigen, moeten we eerst uitzoeken welk proces we willen stoppen. We kunnen alle lopende processen op een externe computer doorlopen door naar de klasse Win32_Process te kijken.

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

Zodra je hebt bepaald welk proces je wilt beëindigen, kun je de naam doorgeven aan de Terminate()-methode op de klasse Win32_Process. Om dat te doen, moet je een instantie van het proces dat je wilt beëindigen vastleggen.

Let hieronder op dat ik de Filter-parameter gebruik om ervoor te zorgen dat ik alleen het ccmexec.exe-proces ontvang. Dit is belangrijk!

Zodra je de instantie hebt vastgelegd, kun je vervolgens de Terminate()-methode aanroepen om het proces te beëindigen met behulp van het Invoke-CimMethod-commando zoals hieronder getoond.

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

Samenvatting

Als je meer wilt weten over het gebruik van WMI in PowerShell en vooral het gebruik van de PowerShell WMI-cmdlet Get-WmiObject dat hier niet is behandeld, moedig ik je aan om Get-WmiObject: Querying WMI on Local and Remote Computers te bekijken waar ik dieper inga op WMI en de Get-WmiObject-cmdlet gebruik.

Voor een volledige uitsplitsing van alle CIM-cmdlets en hoe ze werken in PowerShell, raadpleeg het artikel Introductie tot CIM-cmdlets op Technet. Daar zie je alle verschillende CIM-cmdlets en hoe ze mogelijk worden gebruikt in je scripts.

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