Kapitel 7 – Arbeta med WMI

WMI och CIM

Windows PowerShell levereras som standard med cmdletar för att arbeta med andra tekniker, till exempel Windows Management Instrumentation (WMI). WMI-cmdletarna är inaktuella och är inte tillgängliga i PowerShell 6+, men beskrivs här eftersom du kan stöta på dem i äldre skript som körs i Windows PowerShell. För ny utveckling använder du CIM-cmdletarna i stället.

Det finns flera interna WMI-cmdletar i PowerShell utan att du behöver installera någon annan programvara eller några andra moduler. Get-Command kan användas för att avgöra vilka WMI-cmdletar som finns i Windows PowerShell. Följande resultat kommer från ett Windows 11-system som kör PowerShell version 5.1. Dina resultat kan variera beroende på vilken PowerShell-version du kör.

Get-Command -Noun WMI*
CommandType     Name                                               Version
-----------     ----                                               -------
Cmdlet          Get-WmiObject                                      3.1.0.0
Cmdlet          Invoke-WmiMethod                                   3.1.0.0
Cmdlet          Register-WmiEvent                                  3.1.0.0
Cmdlet          Remove-WmiObject                                   3.1.0.0
Cmdlet          Set-WmiInstance                                    3.1.0.0

CIM-cmdletarna (Common Information Model) introducerades i PowerShell 3.0 och är grupperade i en dedikerad modul. Om du vill visa en lista över alla tillgängliga CIM-cmdletar använder du cmdleten Get-Command med modulparametern , som du ser i följande exempel.

Get-Command -Module CimCmdlets
CommandType     Name                                               Version
-----------     ----                                               -------
Cmdlet          Export-BinaryMiLog                                 1.0.0.0
Cmdlet          Get-CimAssociatedInstance                          1.0.0.0
Cmdlet          Get-CimClass                                       1.0.0.0
Cmdlet          Get-CimInstance                                    1.0.0.0
Cmdlet          Get-CimSession                                     1.0.0.0
Cmdlet          Import-BinaryMiLog                                 1.0.0.0
Cmdlet          Invoke-CimMethod                                   1.0.0.0
Cmdlet          New-CimInstance                                    1.0.0.0
Cmdlet          New-CimSession                                     1.0.0.0
Cmdlet          New-CimSessionOption                               1.0.0.0
Cmdlet          Register-CimIndicationEvent                        1.0.0.0
Cmdlet          Remove-CimInstance                                 1.0.0.0
Cmdlet          Remove-CimSession                                  1.0.0.0
Cmdlet          Set-CimInstance                                    1.0.0.0

Med CIM-cmdletarna kan du fortfarande arbeta med WMI, så bli inte förvirrad när någon säger: "När jag frågar WMI med PowerShell CIM-cmdletarna".

Som tidigare nämnts är WMI en separat teknik från PowerShell, och du använder bara CIM-cmdletarna för att få åtkomst till WMI. Du kan hitta ett gammalt VBScript som använder WMI Query Language (WQL) för att fråga WMI, till exempel i följande exempel.

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

Du kan ta WQL-frågan från VBScript och använda den med cmdleten Get-CimInstance utan några ändringar.

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

Det föregående exemplet är inte hur jag brukar ställa frågor mot WMI med PowerShell. Men det fungerar och gör att du enkelt kan migrera befintliga Visual Basic-skript till PowerShell. När jag skriver en enradare för att fråga WMI använder jag följande syntax.

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

Om du bara vill ha serienumret, skicka utdata till Select-Object och ange endast egenskapen SerialNumber .

Get-CimInstance -ClassName Win32_BIOS |
    Select-Object -Property SerialNumber
SerialNumber
------------
3810-1995-1654-4615-2295-2755-89

När du kör frågor mot WMI hämtas som standard flera egenskaper som aldrig används i bakgrunden. Det spelar ingen roll när du frågar WMI på den lokala datorn. Men när du börjar fråga fjärrdatorer är det inte bara extra bearbetningstid att returnera den informationen utan också mer onödig information att skicka över nätverket. Get-CimInstance har en egenskapsparameter som begränsar den information som hämtas, vilket gör WMI-frågan mer effektiv.

Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber |
    Select-Object -Property SerialNumber
SerialNumber
------------
3810-1995-1654-4615-2295-2755-89

Föregående resultat returnerade ett objekt. Om du vill returnera en sträng använder du parametern ExpandProperty .

Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber |
    Select-Object -ExpandProperty SerialNumber
3810-1995-1654-4615-2295-2755-89

Du kan också använda punktnotation för att returnera en sträng, vilket eliminerar behovet av att skicka till Select-Object.

(Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber).SerialNumber
3810-1995-1654-4615-2295-2755-89

Fråga fjärrdatorer med CIM-cmdletar

Du bör fortfarande köra PowerShell som lokal administratör och domänanvändare. När du försöker fråga efter information från en fjärrdator med hjälp av cmdleten Get-CimInstance får du ett felmeddelande om nekad åtkomst.

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:Stri
   ng) [Get-CimInstance], CimException
    + FullyQualifiedErrorId : HRESULT 0x80070005,Microsoft.Management.Infra
   structure.CimCmdlets.GetCimInstanceCommand
    + PSComputerName        : dc01

Många har säkerhetsproblem när det gäller PowerShell, men du har samma behörigheter i PowerShell som i GUI. Varken mer eller mindre. Problemet i föregående exempel är att användaren som kör PowerShell inte har behörighet att fråga WMI-information från DC01-servern. Du kan starta om PowerShell som domänadministratör eftersom Get-CimInstance det inte finns någon parameter för autentiseringsuppgifter . Men det är ingen bra idé eftersom allt du kör från PowerShell skulle köras som domänadministratör. Beroende på situationen kan det scenariot vara farligt ur säkerhetssynpunkt.

Använd principen om lägsta behörighet och höj till domänadministratörskontot per kommando med hjälp av parametern Credential om ett kommando har ett. Get-CimInstance har ingen parameter för autentiseringsuppgifter , så lösningen i det här scenariot är att skapa en CimSession först. Använd sedan CimSession i stället för ett datornamn för att fråga WMI på fjärrdatorn.

$CimSession = New-CimSession -ComputerName dc01 -Credential (Get-Credential)
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Credential

CIM-sessionen lagrades i en variabel med namnet $CimSession. Observera att du också anger cmdleten Get-Credential inom parenteser så att den körs först, frågar efter alternativa autentiseringsuppgifter innan du skapar den nya sessionen. Jag visar dig ett annat mer effektivt sätt att ange alternativa autentiseringsuppgifter senare i det här kapitlet, men det är viktigt att förstå detta grundläggande begrepp innan det blir mer komplicerat.

Du kan nu använda CIM-sessionen som skapades i föregående exempel med cmdleten Get-CimInstance för att fråga BIOS-informationen från WMI på fjärrdatorn.

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

Det finns flera andra fördelar med att använda CIM-sessioner i stället för att bara ange ett datornamn. När du kör flera frågor till samma dator är det effektivare att använda en CIM-session än att använda datornamnet för varje fråga. Om du skapar en CIM-session konfigureras bara anslutningen en gång. Sedan använder flera frågor samma session för att hämta information. Om du använder datornamnet måste cmdletarna konfigurera och ta bort anslutningen med varje fråga.

Cmdleten Get-CimInstance använder WSMan-protokollet som standard, vilket innebär att fjärrdatorn behöver PowerShell version 3.0 eller senare för att ansluta. Det är faktiskt inte PowerShell-versionen som spelar roll, det är stackversionen. Stackversionen kan fastställas med hjälp av cmdleten Test-WSMan . Det måste vara version 3.0, som du hittar med PowerShell version 3.0 och senare.

Test-WSMan -ComputerName dc01
wsmid           : http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentit
                  y.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 äldre WMI-cmdletarna använder DCOM-protokollet, som är kompatibelt med äldre versioner av Windows. Brandväggen blockerar dock vanligtvis DCOM på nyare versioner av Windows. Med New-CimSessionOption cmdleten kan du skapa en DCOM-protokollanslutning för användning med New-CimSession. Med det här alternativet kan cmdleten Get-CimInstance kommunicera med versioner av Windows så gamla som Windows Server 2000. Den här möjligheten innebär också att PowerShell inte krävs på fjärrdatorn när du använder cmdleten Get-CimInstance med en CimSession konfigurerad för att använda DCOM-protokollet.

Skapa alternativet DCOM-protokoll med hjälp av cmdleten New-CimSessionOption och lagra det i en variabel.

$DCOM = New-CimSessionOption -Protocol Dcom

För effektivitet kan du lagra domänadministratören eller förhöjda autentiseringsuppgifter i en variabel så att du inte ständigt behöver ange dem för varje kommando.

$Cred = Get-Credential
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Credential

Jag har en server med namnet SQL03 som kör Windows Server 2008 (icke-R2). Det är det senaste Windows Server-operativsystemet som inte har PowerShell installerat som standard.

Skapa en CimSession till SQL03 med hjälp av DCOM-protokollet.

$CimSession = New-CimSession -ComputerName sql03 -SessionOption $DCOM -Credential $Cred

Observera i föregående kommando att du anger variabeln med namnet $Cred som värde för parametern Credential i stället för att ange dina autentiseringsuppgifter manuellt igen.

Frågans utdata är desamma oavsett det underliggande protokollet.

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

Cmdleten Get-CimSession används för att se vilka CimSessioner som för närvarande är anslutna och vilka protokoll de använder.

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

Hämta och lagra de tidigare skapade CimSessions i en variabel med namnet $CimSession.

$CimSession = Get-CimSession

Fråga båda datorerna med ett kommando, ett med hjälp av WSMan-protokollet och det andra med 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

En av mina bloggartiklar om WMI- och CIM-cmdletar har en PowerShell-funktion som automatiskt identifierar om du vill använda WSMan eller DCOM och sedan konfigurerar lämplig CIM-session åt dig. Mer information finns i PowerShell-funktion för att skapa CimSessioner till fjärrdatorer med återgång till Dcom.

När du är klar med CIM-sessionerna tar du bort dem med cmdleten Remove-CimSession . För att ta bort alla CIM-sessioner, skicka Get-CimSession till Remove-CimSession.

Get-CimSession | Remove-CimSession

Sammanfattning

I det här kapitlet har du lärt dig hur du använder PowerShell för att arbeta med WMI på lokala datorer och fjärrdatorer. Du har också lärt dig hur du använder CIM-cmdletar för att arbeta med fjärrdatorer med hjälp av WSMan- och DCOM-protokollen.

Recension

  1. Vad är skillnaden mellan WMI- och CIM-cmdletarna?
  2. Vilket protokoll använder cmdleten Get-CimInstance som standard?
  3. Vilka är några fördelar med att använda en CIM-session i stället för att ange ett datornamn med Get-CimInstance?
  4. Hur anger du ett annat protokoll än standardprotokollet för användning med Get-CimInstance?
  5. Hur stänger eller tar du bort CIM-sessioner?

Referenser