共用方式為


第 7 章 - 使用 WMI

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 通訊協定來操作遠端電腦。

回顧

  1. WMI 和 CIM cmdlet 有何差異?
  2. 根據預設,Cmdlet 使用哪個通訊協定?
  3. 使用 CIM 工作階段而非指定 Get-CimInstance 電腦名稱有哪些優點?
  4. 如何指定預設通訊協定以外的替代通訊協定來搭配 Get-CimInstance使用?
  5. 如何關閉或移除 CIM 會話?

參考資料