Hoofdstuk 7 - Werken met WMI
WMI en CIM
Windows PowerShell wordt standaard geleverd met cmdlets voor het werken met andere technologieën, zoals Windows Management Instrumentation (WMI). De WMI-cmdlets zijn afgeschaft en zijn niet beschikbaar in PowerShell 6+, maar worden hier besproken, omdat u ze kunt tegenkomen in oudere scripts die worden uitgevoerd in Windows PowerShell. Voor nieuwe ontwikkeling gebruikt u in plaats daarvan de CIM-cmdlets.
Er zijn verschillende systeemeigen WMI-cmdlets die aanwezig zijn in PowerShell zonder dat u extra software of modules hoeft te installeren. Get-Command
kan worden gebruikt om te bepalen welke WMI-cmdlets er bestaan in Windows PowerShell. De volgende resultaten zijn afkomstig van mijn Windows 10-testomgevingcomputer waarop PowerShell versie 5.1 wordt uitgevoerd. Uw resultaten kunnen verschillen, afhankelijk van de Versie van PowerShell die u gebruikt.
Get-Command -Noun WMI*
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Get-WmiObject 3.1.0.0 Microsof...
Cmdlet Invoke-WmiMethod 3.1.0.0 Microsof...
Cmdlet Register-WmiEvent 3.1.0.0 Microsof...
Cmdlet Remove-WmiObject 3.1.0.0 Microsof...
Cmdlet Set-WmiInstance 3.1.0.0 Microsof...
CIM-cmdlets (Common Information Model) zijn geïntroduceerd in PowerShell versie 3.0. De CIM-cmdlets zijn ontworpen zodat ze kunnen worden gebruikt op zowel Windows- als niet-Windows-computers.
De CIM-cmdlets bevinden zich allemaal in een module. Als u een lijst met de CIM-cmdlets wilt ophalen, gebruikt Get-Command
u deze met de moduleparameter , zoals wordt weergegeven in het volgende voorbeeld.
Get-Command -Module CimCmdlets
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Export-BinaryMiLog 1.0.0.0 CimCmdlets
Cmdlet Get-CimAssociatedInstance 1.0.0.0 CimCmdlets
Cmdlet Get-CimClass 1.0.0.0 CimCmdlets
Cmdlet Get-CimInstance 1.0.0.0 CimCmdlets
Cmdlet Get-CimSession 1.0.0.0 CimCmdlets
Cmdlet Import-BinaryMiLog 1.0.0.0 CimCmdlets
Cmdlet Invoke-CimMethod 1.0.0.0 CimCmdlets
Cmdlet New-CimInstance 1.0.0.0 CimCmdlets
Cmdlet New-CimSession 1.0.0.0 CimCmdlets
Cmdlet New-CimSessionOption 1.0.0.0 CimCmdlets
Cmdlet Register-CimIndicationEvent 1.0.0.0 CimCmdlets
Cmdlet Remove-CimInstance 1.0.0.0 CimCmdlets
Cmdlet Remove-CimSession 1.0.0.0 CimCmdlets
Cmdlet Set-CimInstance 1.0.0.0 CimCmdlets
Met de CIM-cmdlets kunt u nog steeds met WMI werken, dus niet verwarrend wanneer iemand de instructie 'Wanneer ik een query op WMI uitvoert met de PowerShell CIM-cmdlets...'
Zoals ik eerder al zei, is WMI een afzonderlijke technologie van PowerShell en u gebruikt alleen de CIM-cmdlets voor toegang tot WMI. Mogelijk vindt u een oud VBScript dat WMI Query Language (WQL) gebruikt om een query uit te voeren op WMI, zoals in het volgende voorbeeld.
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colBIOS = objWMIService.ExecQuery _
("Select * from Win32_BIOS")
For each objBIOS in colBIOS
Wscript.Echo "Manufacturer: " & objBIOS.Manufacturer
Wscript.Echo "Name: " & objBIOS.Name
Wscript.Echo "Serial Number: " & objBIOS.SerialNumber
Wscript.Echo "SMBIOS Version: " & objBIOS.SMBIOSBIOSVersion
Wscript.Echo "Version: " & objBIOS.Version
Next
U kunt de WQL-query van dat VBScript gebruiken en gebruiken met de Get-CimInstance
cmdlet zonder wijzigingen.
Get-CimInstance -Query 'Select * from Win32_BIOS'
SMBIOSBIOSVersion : 090006
Manufacturer : American Megatrends Inc.
Name : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber : 3810-1995-1654-4615-2295-2755-89
Version : VRTUAL - 4001628
Dat is niet hoe ik doorgaans een query op WMI uitvoert met PowerShell. Maar het werkt wel en stelt u in staat om eenvoudig bestaande VBScripts te migreren naar PowerShell. Wanneer ik een one-liner schrijf om een query uit te voeren op WMI, gebruik ik de volgende syntaxis.
Get-CimInstance -ClassName Win32_BIOS
SMBIOSBIOSVersion : 090006
Manufacturer : American Megatrends Inc.
Name : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber : 3810-1995-1654-4615-2295-2755-89
Version : VRTUAL - 4001628
Als ik alleen het serienummer wil, kan ik de uitvoer doorsluisen naar Select-Object
en alleen de eigenschap SerialNumber opgeven.
Get-CimInstance -ClassName Win32_BIOS | Select-Object -Property SerialNumber
SerialNumber
------------
3810-1995-1654-4615-2295-2755-89
Standaard zijn er verschillende eigenschappen die achter de schermen worden opgehaald die nooit worden gebruikt.
Het maakt mogelijk niet veel uit wanneer u een query uitvoert op WMI op de lokale computer. Maar zodra u externe computers gaat opvragen, is het niet alleen extra verwerkingstijd om die informatie te retourneren, maar ook extra onnodige informatie om over het netwerk te hoeven halen. Get-CimInstance
heeft een eigenschapsparameter die de opgehaalde informatie beperkt. Hierdoor wordt de query efficiënter naar WMI.
Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber |
Select-Object -Property SerialNumber
SerialNumber
------------
3810-1995-1654-4615-2295-2755-89
De vorige resultaten hebben een object geretourneerd. Als u een eenvoudige tekenreeks wilt retourneren, gebruikt u de parameter ExpandProperty .
Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber |
Select-Object -ExpandProperty SerialNumber
3810-1995-1654-4615-2295-2755-89
U kunt ook de gestippelde stijl van de syntaxis gebruiken om een eenvoudige tekenreeks te retourneren. Dit elimineert de noodzaak om door te sluizen naar Select-Object
.
(Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber).SerialNumber
3810-1995-1654-4615-2295-2755-89
Query's uitvoeren op externe computers met de CIM-cmdlets
Ik gebruik PowerShell nog steeds als lokale beheerder die een domeingebruiker is. Wanneer ik query's wil uitvoeren op gegevens van een externe computer met behulp van de Get-CimInstance
cmdlet, krijg ik een foutbericht dat de toegang is geweigerd.
Get-CimInstance -ComputerName dc01 -ClassName Win32_BIOS
Get-CimInstance : Access is denied.
At line:1 char:1
+ Get-CimInstance -ComputerName dc01 -ClassName Win32_BIOS
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (root\cimv2:Win32_BIOS:String) [Get-CimI
nstance], CimException
+ FullyQualifiedErrorId : HRESULT 0x80070005,Microsoft.Management.Infrastructure.Cim
Cmdlets.GetCimInstanceCommand
+ PSComputerName : dc01
Veel mensen hebben beveiligingsproblemen als het gaat om PowerShell, maar de waarheid is dat u precies dezelfde machtigingen hebt in PowerShell als in de GUI. Niet meer en niet minder. Het probleem in het vorige voorbeeld is dat de gebruiker met PowerShell geen rechten heeft om WMI-gegevens op te vragen van de DC01-server. Ik kan PowerShell opnieuw starten als domeinbeheerder omdat Get-CimInstance
ik geen referentieparameter heb. Maar vertrouw me, dat is geen goed idee, omdat alles wat ik voer vanuit PowerShell als domeinbeheerder zou worden uitgevoerd. Dat kan gevaarlijk zijn vanuit een veiligheidsstandpunt, afhankelijk van de situatie.
Met behulp van het principe van minimale bevoegdheden kan ik per opdracht mijn domeinbeheerdersaccount uitbreiden met behulp van de parameter Referentie , als een opdracht er een heeft. Get-CimInstance
heeft geen referentieparameter , dus de oplossing in dit scenario is om eerst een CimSession te maken. Vervolgens gebruik ik de CimSession in plaats van een computernaam om een query uit te voeren op WMI op de externe computer.
$CimSession = New-CimSession -ComputerName dc01 -Credential (Get-Credential)
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Credential
De CIM-sessie is opgeslagen in een variabele met de naam $CimSession
. U ziet dat ik ook de Get-Credential
cmdlet tussen haakjes heb opgegeven, zodat deze eerst wordt uitgevoerd, waarbij ik om alternatieve referenties wordt gevraagd voordat de nieuwe sessie wordt gemaakt. Ik zal u een andere efficiëntere manier laten zien om later in dit hoofdstuk alternatieve referenties op te geven, maar het is belangrijk om dit basisconcept te begrijpen voordat u het ingewikkelder maakt.
De CIM-sessie die in het vorige voorbeeld is gemaakt, kan nu worden gebruikt met de Get-CimInstance
cmdlet om de BIOS-gegevens van WMI op de externe computer op te vragen.
Get-CimInstance -CimSession $CimSession -ClassName Win32_BIOS
SMBIOSBIOSVersion : 090006
Manufacturer : American Megatrends Inc.
Name : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber : 0986-6980-3916-0512-6608-8243-13
Version : VRTUAL - 4001628
PSComputerName : dc01
Er zijn verschillende extra voordelen voor het gebruik van CIM-sessies in plaats van alleen een computernaam op te geven. Wanneer u meerdere query's uitvoert op dezelfde computer, is het gebruik van een CIM-sessie efficiënter dan het gebruik van de computernaam voor elke query. Als u een CIM-sessie maakt, wordt de verbinding slechts eenmaal ingesteld. Vervolgens gebruiken meerdere query's dezelfde sessie om informatie op te halen. Als u de computernaam gebruikt, moeten de cmdlets de verbinding met elke afzonderlijke query instellen en afbreken.
De Get-CimInstance
cmdlet maakt standaard gebruik van het WSMan-protocol, wat betekent dat de externe computer PowerShell versie 3.0 of hoger nodig heeft om verbinding te maken. Het is eigenlijk niet de PowerShell-versie die belangrijk is, het is de stackversie. De stackversie kan worden bepaald met behulp van de Test-WSMan
cmdlet.
Dit moet versie 3.0 zijn. Dat is de versie die u vindt met PowerShell versie 3.0 en hoger.
Test-WSMan -ComputerName dc01
wsmid : http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd
ProtocolVersion : http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd
ProductVendor : Microsoft Corporation
ProductVersion : OS: 0.0.0 SP: 0.0 Stack: 3.0
De oudere WMI-cmdlets gebruiken het DCOM-protocol, dat compatibel is met oudere versies van Windows. Maar DCOM wordt doorgaans geblokkeerd door de firewall op nieuwere versies van Windows. Met de New-CimSessionOption
cmdlet kunt u een DCOM-protocolverbinding maken voor gebruik met New-CimSession
. Hierdoor kan de Get-CimInstance
cmdlet worden gebruikt om te communiceren met versies van Windows zo oud als Windows Server 2000. Dit betekent ook dat PowerShell niet vereist is op de externe computer wanneer u de Get-CimInstance
cmdlet gebruikt met een CimSession die is geconfigureerd voor het gebruik van het DCOM-protocol.
Maak de DCOM-protocoloptie met behulp van de New-CimSessionOption
cmdlet en sla deze op in een variabele.
$DCOM = New-CimSessionOption -Protocol Dcom
Voor efficiëntie kunt u uw domeinbeheerder of verhoogde referenties opslaan in een variabele, zodat u deze niet voortdurend hoeft in te voeren voor elke opdracht.
$Cred = Get-Credential
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Credential
Ik heb een server met de naam SQL03 waarop Windows Server 2008 (niet-R2) wordt uitgevoerd. Het is het nieuwste Windows Server-besturingssysteem waarop PowerShell niet standaard is geïnstalleerd.
Maak een CimSession naar SQL03 met behulp van het DCOM-protocol.
$CimSession = New-CimSession -ComputerName sql03 -SessionOption $DCOM -Credential $Cred
In de vorige opdracht heb ik deze keer de variabele met de naam $Cred
opgegeven als de waarde voor de referentieparameter in plaats van ze handmatig opnieuw in te voeren.
De uitvoer van de query is hetzelfde, ongeacht het onderliggende protocol dat wordt gebruikt.
Get-CimInstance -CimSession $CimSession -ClassName Win32_BIOS
SMBIOSBIOSVersion : 090006
Manufacturer : American Megatrends Inc.
Name : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber : 7237-7483-8873-8926-7271-5004-86
Version : VRTUAL - 4001628
PSComputerName : sql03
De Get-CimSession
cmdlet wordt gebruikt om te zien welke CimSessions momenteel zijn verbonden en welke protocollen ze gebruiken.
Get-CimSession
Id : 1
Name : CimSession1
InstanceId : 80742787-e38e-41b1-a7d7-fa1369cf1402
ComputerName : dc01
Protocol : WSMAN
Id : 2
Name : CimSession2
InstanceId : 8fcabd81-43cf-4682-bd53-ccce1e24aecb
ComputerName : sql03
Protocol : DCOM
Haal beide eerder gemaakte CimSessions op en sla deze op in een variabele met de naam $CimSession
.
$CimSession = Get-CimSession
Voer een query uit op beide computers met één opdracht, één met behulp van het WSMan-protocol en de andere met DCOM.
Get-CimInstance -CimSession $CimSession -ClassName Win32_BIOS
SMBIOSBIOSVersion : 090006
Manufacturer : American Megatrends Inc.
Name : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber : 0986-6980-3916-0512-6608-8243-13
Version : VRTUAL - 4001628
PSComputerName : dc01
SMBIOSBIOSVersion : 090006
Manufacturer : American Megatrends Inc.
Name : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber : 7237-7483-8873-8926-7271-5004-86
Version : VRTUAL - 4001628
PSComputerName : sql03
Ik heb talloze blogartikelen geschreven over de WMI- en CIM-cmdlets. Een van de handigste is over een functie die ik heb gemaakt om automatisch te bepalen of WSMan of DCOM moet worden gebruikt en de CIM-sessie automatisch moet instellen zonder dat u hoeft te achterhalen welke handmatig. Dit blogartikel heeft de titel PowerShell-functie voor het maken van CimSessions voor externe computers met terugval naar Dcom.
Wanneer u klaar bent met de CIM-sessies, moet u deze verwijderen met de Remove-CimSession
cmdlet. Als u alle CIM-sessies wilt verwijderen, sluist Get-CimSession
u gewoon door naar Remove-CimSession
.
Get-CimSession | Remove-CimSession
Samenvatting
In dit hoofdstuk hebt u geleerd hoe u PowerShell kunt gebruiken om met WMI te werken op zowel lokale als externe computers. U hebt ook geleerd hoe u de CIM-cmdlets gebruikt om te werken met externe computers met zowel het WSMan- als DCOM-protocol.
Beoordelen
- Wat is het verschil in de WMI- en CIM-cmdlets?
- Welk protocol gebruikt de
Get-CimInstance
cmdlet standaard? - Wat zijn enkele voordelen van het gebruik van een CIM-sessie in plaats van een computernaam op te geven met
Get-CimInstance
? - Hoe geeft u een ander alternatief protocol op dan de standaardprotocol voor gebruik met
Get-CimInstance
? - Hoe sluit of verwijdert u CIM-sessies?