WMI 和 CIM
根據預設,Windows PowerShell 隨附 Cmdlet 以處理其他技術,例如 Windows Management Instrumentation (WMI)。 WMI Cmdlet 已被取代,無法在 PowerShell 6+ 中使用,但這裡涵蓋,因為您可能會在 Windows PowerShell 上執行的舊版腳本中遇到它們。 針對新的開發,請改用 CIM Cmdlet。
PowerShell 中存在數個原生 WMI Cmdlet,而不需要安裝任何其他軟體或模組。
Get-Command 可用來判斷 Windows PowerShell 中有哪些 WMI Cmdlet。 下列結果來自執行 PowerShell 5.1 版的 Windows 11 系統。 您的結果可能會因您執行的PowerShell版本而有所不同。
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
Common Information Model (CIM) Cmdlet 是在 PowerShell 3.0 中引進,並分組在專用模組內。 若要列出所有可用的 CIM Cmdlet,請使用 Get-Command Cmdlet 搭配 Module 參數,如下列範例所示。
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
CIM Cmdlet 仍然可讓您使用 WMI,因此當有人指出 :「當我使用 PowerShell CIM Cmdlet 查詢 WMI 時」時,請勿混淆。
如先前所述,WMI 是與 PowerShell 不同的技術,而您只是使用 CIM Cmdlet 來存取 WMI。 您可能會發現使用 WMI 查詢語言 (WQL) 來查詢 WMI 的舊 VBScript,如下列範例所示。
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
您可以從 VBScript 取得 WQL 查詢,並搭配 Get-CimInstance Cmdlet 使用它,而不需要進行任何修改。
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
上述範例不是我通常會使用PowerShell查詢 WMI的方式。 但它可運作,並可讓您輕鬆地將現有的Visual Basic腳本移轉至PowerShell。 撰寫單行來查詢 WMI 時,我使用下列語法。
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
如果您只想要序號,請將輸出透過管道傳送至 Select-Object,並只指定 SerialNumber 屬性。
Get-CimInstance -ClassName Win32_BIOS |
Select-Object -Property SerialNumber
SerialNumber
------------
3810-1995-1654-4615-2295-2755-89
根據預設,查詢 WMI 時,會擷取幕後永遠不會使用的數個屬性。 在本機計算機上查詢 WMI 時並不重要。 但是,一旦您開始查詢遠端計算機,不僅需要額外的處理時間才能傳回該資訊,而且需要更多不必要的資訊才能透過網路傳送。
Get-CimInstance 具有 屬性 參數,可限制擷取的資訊,讓WMI查詢更有效率。
Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber |
Select-Object -Property SerialNumber
SerialNumber
------------
3810-1995-1654-4615-2295-2755-89
先前的結果已傳回一個物件。 若要傳回字串,請使用 ExpandProperty 參數。
Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber |
Select-Object -ExpandProperty SerialNumber
3810-1995-1654-4615-2295-2755-89
您也可以使用虛線語法樣式來傳回字串,而不需要使用管線傳送至 Select-Object。
(Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber).SerialNumber
3810-1995-1654-4615-2295-2755-89
使用 CIM Cmdlet 查詢遠端電腦
您仍應以本機系統管理員和網域使用者身分執行 PowerShell。 當您嘗試使用 Get-CimInstance Cmdlet 從遠端電腦查詢資訊時,您會收到拒絕存取的錯誤訊息。
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
許多人對於PowerShell有安全性考慮,但您在PowerShell中擁有與 GUI 中相同的許可權。 不多也不少。 上一個範例中的問題在於執行 PowerShell 的用戶沒有從 DC01 伺服器查詢 WMI 資訊的許可權。 您可以將PowerShell重新啟動為網域系統管理員,因為 Get-CimInstance 沒有 Credential 參數。 但這不是個好主意,因為您從 PowerShell 執行的任何項目都會以網域系統管理員身分執行。視情況而定,從安全觀點來看,該案例可能很危險。
根據最低許可權原則,當命令具有 Credential 參數時,請依每個命令升級權限到網域系統管理員帳戶。
Get-CimInstance 沒有 Credential 參數,因此此案例中的解決方案是先建立 CimSession 。
然後,使用 CimSession 而不是計算機名稱來查詢遠端電腦上的 WMI。
$CimSession = New-CimSession -ComputerName dc01 -Credential (Get-Credential)
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Credential
CIM 會話儲存在名為的 $CimSession變數中。 請注意,您也會在括弧中指定 Get-Credential Cmdlet,以便在建立新的工作階段之前先執行,提示輸入替代認證。 我在本章稍後示範另一個更有效率的方式來指定替代認證,但請務必先了解這個基本概念,再讓認證變得更複雜。
您現在可以使用上一個範例中建立的 CIM 會話搭配 Get-CimInstance Cmdlet,從遠端電腦上的 WMI 查詢 BIOS 資訊。
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
使用 CIM 會話有數個其他優點,而不只是指定計算機名稱。 當您對同一部計算機執行多個查詢時,使用 CIM 會話比針對每個查詢使用電腦名稱更有效率。 建立 CIM 會話只會設定連線一次。 然後,多個查詢會使用該相同的會話來擷取資訊。 使用計算機名稱需要 cmdlet 來設定和關閉每次查詢的連線。
Cmdlet Get-CimInstance 預設會使用 WSMan 通訊協定,這表示遠端電腦需要 PowerShell 3.0 版或更高版本才能連線。 其實重要的不是 PowerShell 版本,而是堆疊版本。 您可以使用 Cmdlet 來判斷 Test-WSMan 堆疊版本。
它必須是 3.0 版,您需要使用 PowerShell 3.0 版或更高版本才能找到。
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
較舊的 WMI Cmdlet 會使用與舊版 Windows 相容的 DCOM 通訊協定。
不過,防火牆通常會封鎖較新版本 Windows 上的 DCOM。 Cmdlet New-CimSessionOption 可讓您建立 DCOM 通訊協定連線,以搭配 New-CimSession使用。 此選項可讓 Get-CimInstance Cmdlet 與舊版 Windows,包括最早至 Windows Server 2000 的版本,進行通訊。這項功能同時表示,當使用設定為採用 DCOM 通訊協定的 CimSession 時,無需在遠端電腦上安裝 PowerShell,即可使用 Get-CimInstance Cmdlet。
使用 New-CimSessionOption Cmdlet 建立 DCOM 通訊協定選項,並將其儲存在變數中。
$DCOM = New-CimSessionOption -Protocol Dcom
為了提高效率,您可以將網域系統管理員或提升許可權的認證儲存在變數中,因此您不需要持續輸入每個命令。
$Cred = Get-Credential
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Credential
我有一個名為 SQL03 的伺服器,其執行 Windows Server 2008 (非 R2)。 這是預設未安裝 PowerShell 的最新 Windows Server作系統。
建立 CimSession,使用 DCOM 通訊協定連接至 SQL03。
$CimSession = New-CimSession -ComputerName sql03 -SessionOption $DCOM -Credential $Cred
請注意,在上一個命令中,您會將名為 $Cred 的變數指定為 Credential 參數的值,而不是再次手動輸入認證。
不論基礎通訊協議為何,查詢的輸出都相同。
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
Cmdlet Get-CimSession 可用來查看目前連線的 CimSession,以及其所使用的通訊協定。
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
擷取並儲存先前建立的 CimSessions 在名為 $CimSession的變數中。
$CimSession = Get-CimSession
使用一個命令來查詢這兩部計算機,一部使用WSMan通訊協定,另一個則使用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
我關於 WMI 和 CIM Cmdlet 的其中一篇部落格文章具有 PowerShell 函式,可自動偵測要使用 WSMan 或 DCOM,然後為您設定適當的 CIM 會話。 如需詳細資訊,請參閱 使用 Dcom 做為後援機制以建立 CimSessions 至遠端電腦的 PowerShell 函數。
當您完成 CIM 工作階段時,請使用 Remove-CimSession Cmdlet 移除它們。 若要移除所有 CIM 工作階段,請透過管線將 Get-CimSession 傳送至 Remove-CimSession。
Get-CimSession | Remove-CimSession
總結
在本章中,您已瞭解如何使用PowerShell在本機和遠端電腦上使用 WMI。 您也瞭解如何使用 CIM cmdlets 透過 WSMan 和 DCOM 通訊協定來操作遠端電腦。
回顧
- WMI 和 CIM cmdlet 有何差異?
- 根據預設,Cmdlet 使用哪個通訊協定?
- 使用 CIM 工作階段而非指定
Get-CimInstance電腦名稱有哪些優點? - 如何指定預設通訊協定以外的替代通訊協定來搭配
Get-CimInstance使用? - 如何關閉或移除 CIM 會話?