PowerShell WMI:自動執行Windows任務

Windows Management Instrumentation(WMI)在Windows上已存在很長一段時間。許多IT專業人員直接使用WMI或使用從WMI讀取信息的工具。您知道PowerShell WMI cmdlets是內置的嗎?

WMI是收集有關Windows機器信息和操縱Windows內部各種服務的事實標準位置。由於WMI提供了廣泛的信息,您可以通過使用Powershell WMI來利用它。使用PowerShell查詢WMI允許您自動執行Windows計算機上的數千個任務。

幸運的是,PowerShell最早為WMI提供了命令。由於您具有本地的PowerShell WMI cmdlets,這意味著IT管理員可以利用PowerShell易於理解的動詞/名詞語法與WMI進行交互,並且,正如您將看到的,高級用戶也可以使用標准的PowerShell命令直接調用WMI事件和類。

PowerShell WMI cmdlets vs CIM

在使用PowerShell使用WMI時,存在兩組命令。有些人將這些命令集稱為與WMI交互的“舊”方式和CIM cmdlets。從WMI查詢信息時,兩者返回相同的信息,但處理方式略有不同。從WMI讀取信息的“舊”方式是使用Get-WmiObject命令。其他WMI cmdlets包括Invoke-WmiMethodRegister-WMIEvent等,但我們在本文中不會涵蓋這些內容。

PowerShell WMI cmdlet Get-WmiObject 可以運作,但有一個嚴重的缺點。在查詢遠端電腦時,它依賴於 DCOM,而 DCOM 在過去一直是惡意程式的攻擊向量。DCOM 通常被各種防火牆阻擋。由於這是「舊」的方法,我們不會深入探討這個方法。相反,我們將專注於 CIM cmdlet,主要是 Get-CimInstance

DCOM Component Services

Get-WmiObjectGet-CimInstance 的最大差異在於,Get-CimInstance 不使用 DCOM 來存取遠端電腦,而是使用 WSMAN 協議,這是熟悉的 PowerShell 遠端管理功能的傳輸方式。

PowerShell CIM Cmdlets

假設您想要返回有關遠端電腦上的 Windows 版本的一些資訊。在這個例子中,我想從一台名為 DC 的電腦中取得一些資訊。您可以透過指定包含資訊的 WMI 類別和要查詢的電腦名稱來達到這個目的。

如下所示,由於 Get-CimInstance 在預設情況下不顯示類別中的所有屬性,我必須將輸出導向 Select-Object 命令以返回所有屬性。

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-

不僅可以通過屬性收集信息,還可以在類上調用WMI/CIM方法。其中一個很好的例子是停止遠程計算機上的進程。在PowerShell中,原生的Stop-Process命令無法實現這一點。然而,通過WMI查詢是可行的。為了終止遠程進程,我們首先需要找出要終止的進程。可以通過查看Win32_Process類來列舉遠程計算機上的所有運行中進程。

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

找到要終止的進程後,可以將其名稱傳遞給Win32_Process類的Terminate()方法。為此,需要捕獲要終止的進程實例。

請注意,下面的代碼示例中,我使用Filter參數確保只接收ccmexec.exe進程。這一點很重要!

捕獲到進程實例後,可以使用Invoke-CimMethod命令調用Terminate()方法終止進程,如下所示。

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

總結

如果您想了解更多關於在PowerShell中使用WMI,特別是使用這裡未涉及的PowerShell WMI cmdlet Get-WmiObject的信息,建議您查看Get-WmiObject: 在本地和遠程計算機上查詢WMI,其中更深入地介紹了WMI和使用Get-WmiObject cmdlet的方法。

有關CIM cmdlets的詳細解析和在PowerShell中的工作方式,請參考Technet上的介紹CIM Cmdlets文章。在那裡,您將看到所有不同的CIM cmdlets以及它們在腳本中的使用方式。

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