PowerShell WMI: Windowsタスクの自動化

Windows管理インストゥルメンテーション(WMI)は、Windowsで長い間使われてきました。多くのITプロは、直接WMIを使用するか、WMIから情報を読み取るツールを使用しています。PowerShellのWMIコマンドレットが組み込まれていることをご存知でしょうか?

WMIは、Windowsマシンの情報を収集し、Windows内部のさまざまなサービスを操作するための事実上の場所です。WMIの幅広い情報にアクセスできるため、PowerShellを使用してWMIを問い合わせることができます。PowerShellを使用してWMIを照会することで、Windowsコンピュータ上で数千のタスクを自動化することができます。

幸いなことに、PowerShellの最初のシステムの1つはWMI用のコマンドでした。ネイティブのPowerShell WMIコマンドレットがあるため、IT管理者はPowerShellの分かりやすい動詞/名詞の構文を活用してWMIと対話することができます。また、パワーユーザーは標準のPowerShellコマンドを使用するだけで、WMIのイベントやクラスを直接呼び出すこともできます。

PowerShell WMIコマンドレットとCIM

PowerShellでWMIを使用する場合、2つの「セット」のコマンドがあります。これらの「セット」は、WMIとの対話の「古い」方法とCIMコマンドレットとして言及されることもあります。WMIから情報をクエリする際、どちらも同じ情報を返しますが、少し異なる方法でアプローチします。「古い」方法は、Get-WmiObjectコマンドを使用してWMIから情報を読み取ることです。その他のWMIコマンドレットには、Invoke-WmiMethodRegister-WMIEventなどがありますが、この記事ではこれらをカバーしません。

PowerShellのWMIコマンドレットGet-WmiObjectは機能しますが、重大な欠点があります。リモートコンピュータのクエリには、DCOMを使用しており、DCOMは過去における攻撃手段とされています。DCOMは通常、さまざまなファイアウォールでブロックされています。これが「古い」方法であるため、この方法については詳しく説明しません。代わりに、CIMコマンドレットに焦点を当てます:主に、Get-CimInstanceです。

DCOM Component Services

Get-WmiObjectGet-CimInstanceの大きな違いは、Get-CimInstanceがリモートコンピュータにアクセスするためにDCOMを使用せず、Get-CimInstanceはなじみのあるPowerShellリモーティング機能のための輸送手段であるWSMANプロトコルを使用していることです。

PowerShell CIMコマンドレット

たとえば、リモートコンピュータの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

終了したいプロセスを特定したら、そのプロセスのインスタンスをキャプチャする必要があります。

以下の例では、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コマンドレットGet-WmiObjectの使用についてさらに学びたい場合は、Get-WmiObject: ローカルおよびリモートコンピュータ上のWMIのクエリを参照することをお勧めします。そこでは、WMIについてより詳しく説明し、Get-WmiObjectコマンドレットを使用します。

PowerShellでのCIM cmdletの詳細な説明については、Technetの「CIM Cmdletsの紹介」記事を参照してください。そこでは、さまざまなCIM cmdletとそれらがスクリプトでどのように使用されるかが示されています。

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