Open7

🛠 入門 WMI: Windows Management Instrumentation

ピン留めされたアイテム
sheeplasheepla

はじめに

sheeplasheepla

WMIとは

Windows オペレーティングシステムの管理情報と操作機能を提供するフレームワーク。簡単に言うと、Windows のシステム情報を取得したり、設定を変更したり、サービスを制御したりするための APIやその枠組みのこと。

WMIの用途

WMI は 「Windowsの管理と監視のための共通API」 として、次のような用途で広く使われている。

  • 運用管理(構成収集・監視・一括操作)
  • セキュリティ監視
  • 自動化スクリプト

システム監視・インベントリ収集

  • PCやサーバの構成情報取得

    • OSバージョン、CPU、メモリ、ディスク容量
    • ネットワーク構成やMACアドレス
  • 資産管理ツール

    • SCCM(System Center Configuration Manager)などが内部でWMIを利用
  • 監視ツール

    • Zabbix、Nagios、PRTG、PrometheusなどでWindows監視時にWMIでCPUやメモリ使用率を取得

障害対応・ログ収集

  • イベントログ収集

    • セキュリティログやシステムログの監視
    • ブルースクリーンやドライバ問題調査
    • WMIでハードウェアステータスやエラーメッセージ取得

リモートからの一括管理操作

  • 大量のPCに対する一括操作
    • サービスの起動・停止
    • プロセスの強制終了
    • ファイル配布やスクリプト実行
  • PowerShell Remotingによるドメイン全体の制御

セキュリティ監視

  • 不審なプロセスやスクリプトの検出

  • WMIイベントサブスクリプションを悪用したマルウェア検出

  • EDR製品

  • WMIでシステム状態をモニタリング

自動化スクリプト

  • PowerShellやVBScriptでの運用タスク自動化
  • 例:ログインユーザーの一覧取得
  • 例:USB接続デバイスの確認

ハードウェア・ドライバ情報取得

  • メーカー製管理ツール
  • Dell、HP、Lenovoなどの管理ソフトがWMI経由でハードウェア情報を取得
  • BIOS情報、温度センサー値
  • Win32_BIOS, MSAcpi_ThermalZoneTemperature などのWMIクラスを利用
sheeplasheepla

CIM: Common Information ModelとWMI

CIM: Common Information Modelは業界標準の管理モデルを定義したもので、WMIはそれをWindows上で実装したしくみ。

sheeplasheepla

WMIの基本モデル

WMIは、オブジェクト指向のモデルに基づき、管理対象をクラスとインスタンスで表現する。このモデルは、業界標準であるCIM(Common Information Model)をベースにしており、Windows環境に特化した拡張が加えられている。

WMIの構造は、大きく分けて次の要素で構成される。

  • 名前空間(Namespace)
  • クラス(Class)
  • インスタンス(Instance)
  • プロパティとメソッド
  • MOF(Managed Object Format)
  • プロバイダー(Provider)
  • WMIリポジトリ(Repository)
  • イベント(Event)

以下、それぞれを詳しく見ていく。

名前空間(Namespace)

名前空間は、WMIクラスを分類するための論理的なコンテナ。最もよく使われるのは root\cimv2 で、OSやハードウェアに関する標準クラスが格納されている。他にも、イベント関連の root\subscription や、アプリケーション固有の名前空間が存在する。

PowerShellでは、次のようにして名前空間を列挙できる。

Get-WmiObject -Namespace root -Class __Namespace

クラス(Class)

WMIにおけるクラスは、管理対象を表現するための雛形。例えば、Win32_Process クラスはWindows上のプロセスを、Win32_OperatingSystem クラスはOS自体を表す。

クラスは、プロパティ(情報を表す属性)とメソッド(操作を提供する関数)を持つ。たとえば、Win32_Process クラスにはプロセス名を表す Name プロパティや、プロセスを終了する Terminate() メソッドがある。

PowerShellでは、クラスのインスタンスだけでなく、クラス定義そのもののメタデータを取得することもできる。これには、[__meta_class] クエリを使用する。

# クラス定義を取得する例
Get-WmiObject -Query "SELECT * FROM meta_class WHERE __CLASS = 'Win32_Process'"

このクエリを実行すると、クラスのプロパティ、メソッド、修飾子など、定義情報を確認できる。__meta_class は特別なWMIシステムクラスであり、スキーマ情報にアクセスするために使う。

インスタンス(Instance)

クラスは抽象的な定義だが、実際に動いているプロセスやOS情報は「インスタンス」として表現される。例えば、Win32_Process クラスに対して、notepad.exeexplorer.exe が個別のインスタンスになる。

プロパティとメソッド

インスタンスが持つ情報は「プロパティ」として提供される。Win32_OperatingSystem なら、OS名やバージョン、メモリ容量といった情報。また、WMIクラスには操作を実行する「メソッド」というものも用意されており、例えば Win32_Service クラスではサービスの開始や停止を行うメソッドが用意されている。

MOF(Managed Object Format)

WMIクラスは、MOFと呼ばれるテキスト形式のスキーマで定義される。MOFは、名前空間、クラス、プロパティ、メソッドの定義を含むIDL(Interface Definition Language)に似た言語。

例えば、Win32_OperatingSystem クラスの簡略化したMOFは次のとおり。

[dynamic, provider("WMIProv")]
class Win32_OperatingSystem {
    string Caption;
    string Version;
    datetime InstallDate;
    uint64 TotalVisibleMemorySize;
};

この定義はWMIリポジトリに登録され、WMIサービスがアクセスできるようになる。

実体としてのMOFファイルは、Windowsの %SystemRoot%\System32\wbem ディレクトリに配置されており、*.mof*.mfl ファイルがそれにあたる。これらはシステムクラスやWin32クラスなど、標準で提供されるWMIクラスの定義を含む。管理者や開発者は独自のMOFを定義して登録し、カスタムクラスを追加することもできる。

WMIリポジトリ

WMIリポジトリは、WMIクラス定義や一部のインスタンス情報を格納するデータベース。通常、%SystemRoot%\System32\wbem\Repository に存在し、WMIサービスによって管理される。

プロバイダー(Provider)

WMIそのものはデータを直接保持しない。実際にデータを取得するのはプロバイダー。プロバイダーは、カーネルAPIやハードウェアドライバ、サービスなどから情報を取得し、WMIクラスを通して公開する。

イベント(Event)

WMIは、単なる情報取得だけでなく、イベント通知機能も提供する。例えば、新しいプロセスが生成されたときや、サービスが停止したときにイベントを発行できる。これにより、監視やトリガー処理が可能になる。

まとめ

WMIは、名前空間とクラスを基盤に、Windowsの管理情報をオブジェクト指向モデルで統一的に扱える仕組み。MOFで定義されたクラスはWMIリポジトリに格納され、プロバイダーを介してリアルタイムな情報にアクセスする。また、イベント通知を利用すれば、状態変化をトリガーにした自動化することもできる。

sheeplasheepla

WMIの名前空間の階層と代表的なクラス

WMIの名前空間の改装および代表的なクラスをまとめると次のようになる。

root -- WMIの最上位名前空間
├─ subscription -- イベント通知やサブスクリプション関連
│
├─ DEFAULT -- 汎用的な管理クラスが含まれる
│
├─ CIMV2 -- Windowsの主要な管理情報(OS、プロセス、ハードウェア)
│   ├─ Win32_OperatingSystem -- OS情報(名前、バージョン)
│   ├─ Win32_Process -- プロセス情報(PID、状態)
│   ├─ Win32_LogicalDisk -- 論理ディスク情報(空き容量、ファイルシステム)
│   ├─ Win32_NetworkAdapter -- ネットワークアダプタ情報(MAC、状態)
│   └─ CIM_ComputerSystem -- コンピュータ情報(メーカー、モデル)
│
├─ SECURITY -- セキュリティ構成情報を管理
│
├─ SecurityCenter2 -- セキュリティ製品(ウイルス対策ソフト)の状態
│   ├─ AntiVirusProduct -- インストールされたウイルス対策ソフト
│   ├─ FirewallProduct -- ファイアウォール情報
│   └─ AntiSpywareProduct -- スパイウェア対策製品情報
│
├─ WMI -- WMIプロバイダーや構成情報
│
├─ Microsoft -- Microsoft製品の管理情報
│   └─ Windows -- Windowsコンポーネントの設定情報
│      ├─ Defender -- Windows Defender関連
│      │   ├─ MSFT_MpPreference -- Defenderの設定
│      │   └─ MSFT_MpThreatDetection -- 脅威検出情報
│      ├─ PowerShellv3 -- PowerShellの実行ポリシーやセッション
│      └─ Update -- Windows Update情報
│
├─ RSOP -- グループポリシー適用結果(Resultant Set of Policy)
│   ├─ Computer -- コンピュータポリシー
│   └─ User -- ユーザポリシー
│
├─ StandardCimv2 -- CIMベースの標準管理情報(PowerShellのCIMコマンドで利用)
│   ├─ MSFT_NetAdapter -- ネットワークアダプタ管理
│   ├─ MSFT_NetIPAddress -- IPアドレス設定
│   ├─ MSFT_Disk -- ディスク管理
│   ├─ MSFT_Volume -- ボリューム管理
│   └─ MSFT_Printer -- プリンタ管理
│
└─ virtualization -- Hyper-V関連
    └─ v2 -- Hyper-V仮想化プラットフォームの管理
        ├─ Msvm_ComputerSystem -- ホストおよびVMの状態
        ├─ Msvm_VirtualSystemSettingData -- 仮想マシン設定
        ├─ Msvm_MemorySettingData -- メモリ設定
        ├─ Msvm_ProcessorSettingData -- CPU設定
        └─ Msvm_VirtualEthernetSwitch -- 仮想スイッチ情報

sheeplasheepla

PowerShellでWMIにアクセスしてみよう

TODO

sheeplasheepla

C++でWMIにアクセスしてみよう

基本概念

WMIにアクセスするためのAPIは、COMインターフェースとして提供される。主要なCOMインタフェースとして次のものがある。

  • IWbemLocator : WMIサービスに接続する
  • IWbemServices : WMIクラス・インスタンスにアクセスする
  • IEnumWbemClassObject : クエリ結果を列挙する
  • IWbemClassObject : 個々のWMIオブジェクトを表す

また、COMの初期化時には CoInitiaizeExによりシングルスレッド COINIT_APARTMENT_THREADED またはマルチスレッド COINIT_MULTITHREADED のいずれかを指定し、CoInitializeSecurity によりセキュリティコンテキストを初期化する必要がある。

手順

以下に典型的な流れを示す。

1. COMライブラリの初期化 (CoInitializeEx)

WMIを使用する前に、COMライブラリを初期化する必要がある。
CoInitializeEx はスレッド単位でCOMを初期化し、スレッドモデルを指定する。

HRESULT CoInitializeEx(
    LPVOID pvReserved, // 予約。必ず NULL を指定
    DWORD dwCoInit     // スレッドの並列モデルを指定
                       //   COINIT_APARTMENTTHREADED : シングルスレッドアパートメント
                       //   COINIT_MULTITHREADED     : マルチスレッドアパートメント
);

例えば、マルチスレッドアパートメントモデルで初期化するには次のように呼び出す。

HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hr)) {
    wprintf(L"Failed to initialize COM library. Error code = 0x%X\n", hr);
    return 1; // エラー処理
}

2. COMセキュリティの初期化 (CoInitializeSecurity)

WMIの呼び出しには、COMセキュリティの初期化が必要になる。
CoInitializeSecurity は、プロセス全体のセキュリティ設定を構成する。

HRESULT CoInitializeSecurity(
    PSECURITY_DESCRIPTOR pSecDesc, // セキュリティ記述子(通常 NULL)
    LONG cAuthSvc,                 // 認証サービスの数(-1 は既定の設定を使用)
    SOLE_AUTHENTICATION_SERVICE *asAuthSvc, // 認証サービス配列(通常 NULL)
    void *pReserved1,              // 予約。NULL
    DWORD dwAuthnLevel,            // 認証レベル(例: RPC_C_AUTHN_LEVEL_DEFAULT)
    DWORD dwImpLevel,              // 偽装レベル(例: RPC_C_IMP_LEVEL_IMPERSONATE)
    void *pAuthList,               // 認証情報(通常 NULL)
    DWORD dwCapabilities,          // 追加の機能(例: EOAC_NONE)
    void *pReserved3               // 予約。NULL
);

例えば、既定の認証レベルで初期化するには次のように呼び出す。

HRESULT hr = CoInitializeSecurity(
    NULL,
    -1,
    NULL,
    NULL,
    RPC_C_AUTHN_LEVEL_DEFAULT,
    RPC_C_IMP_LEVEL_IMPERSONATE,
    NULL,
    EOAC_NONE,
    NULL
);
if (FAILED(hr)) {
    wprintf(L"Failed to initialize security. Error code = 0x%X\n", hr);
    CoUninitialize();
    return 1;
}

3. IWbemLocator オブジェクトの作成 (CoCreateInstance)

WMIサービスに接続するために、IWbemLocator のインスタンスを作成する。

HRESULT CoCreateInstance(
    REFCLSID rclsid,   // 作成するオブジェクトのCLSID
    LPUNKNOWN pUnkOuter, // 集約オブジェクト(通常 NULL)
    DWORD dwClsContext,  // 実行コンテキスト(CLSCTX_INPROC_SERVER など)
    REFIID riid,         // 要求するインターフェースのIID
    LPVOID *ppv          // 作成されたオブジェクトを受け取るポインタ
);

例えば、IWbemLocator を作成するには次のように呼び出す。

IWbemLocator *pLocator = NULL;
HRESULT hr = CoCreateInstance(
    CLSID_WbemLocator,
    0,
    CLSCTX_INPROC_SERVER,
    IID_IWbemLocator,
    (LPVOID *)&pLocator
);
if (FAILED(hr)) {
    wprintf(L"Failed to create IWbemLocator object. Error code = 0x%X\n", hr);
    CoUninitialize();
    return 1;
}

4. WMIサービスに接続する (IWbemLocator::ConnectServer)

IWbemLocator を使って、指定した名前空間のWMIサービス (IWbemServices) に接続する。

HRESULT IWbemLocator::ConnectServer(
    const BSTR strNetworkResource, // 接続するWMI名前空間(例: L"ROOT\\CIMV2")
    const BSTR strUser,            // ユーザー名(NULL は現在のユーザー)
    const BSTR strPassword,        // パスワード(NULL は現在のユーザー)
    const BSTR strLocale,          // ロケール(通常 NULL)
    LONG lSecurityFlags,           // セキュリティフラグ(通常 0)
    const BSTR strAuthority,       // 認証情報(通常 NULL)
    IWbemContext *pCtx,            // コンテキスト情報(通常 NULL)
    IWbemServices **ppNamespace    // 接続先の IWbemServices オブジェクト
);

例えば、ローカルの ROOT\CIMV2 に接続するには次のように呼び出す。

IWbemServices *pServices = NULL;
HRESULT hr = pLocator->ConnectServer(
    _bstr_t(L"ROOT\\CIMV2"),
    NULL,
    NULL,
    NULL,
    0,
    NULL,
    NULL,
    &pServices
);
if (FAILED(hr)) {
    wprintf(L"Could not connect to WMI namespace. Error code = 0x%X\n", hr);
    pLocator->Release();
    CoUninitialize();
    return 1;
}

5. セキュリティレベルの設定 (CoSetProxyBlanket)

WMIのインターフェース呼び出しに必要な認証情報を設定する。

HRESULT CoSetProxyBlanket(
    IUnknown *pProxy,             // 対象のプロキシ(通常 IWbemServices)
    DWORD dwAuthnSvc,             // 認証サービス(例: RPC_C_AUTHN_WINNT)
    DWORD dwAuthzSvc,             // 認可サービス(例: RPC_C_AUTHZ_NONE)
    OLECHAR *pServerPrincName,    // サーバー名(通常 NULL)
    DWORD dwAuthnLevel,           // 認証レベル(例: RPC_C_AUTHN_LEVEL_CALL)
    DWORD dwImpLevel,             // 偽装レベル(例: RPC_C_IMP_LEVEL_IMPERSONATE)
    RPC_AUTH_IDENTITY_HANDLE pAuthInfo, // 認証情報(NULL は既定)
    DWORD dwCapabilities          // 追加機能(例: EOAC_NONE)
);

例えば、既定の認証レベルで設定するには次のように呼び出す。

HRESULT hr = CoSetProxyBlanket(
    pServices,
    RPC_C_AUTHN_WINNT,
    RPC_C_AUTHZ_NONE,
    NULL,
    RPC_C_AUTHN_LEVEL_CALL,
    RPC_C_IMP_LEVEL_IMPERSONATE,
    NULL,
    EOAC_NONE
);
if (FAILED(hr)) {
    wprintf(L"Could not set proxy blanket. Error code = 0x%X\n", hr);
    pServices->Release();
    pLocator->Release();
    CoUninitialize();
    return 1;
}

6. オブジェクトの操作 (IWbemServices::ExecQuery)

IWbemServices を使ってWQLクエリを実行し、対象オブジェクトを列挙する。

HRESULT IWbemServices::ExecQuery(
    const BSTR strQueryLanguage,    // クエリ言語(通常は "WQL")
    const BSTR strQuery,            // WQLクエリ文字列(例: "SELECT * FROM Win32_Process")
    long lFlags,                    // 実行フラグ(WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY)
    IWbemContext *pCtx,             // コンテキスト情報(通常 NULL)
    IEnumWbemClassObject **ppEnum   // 結果を受け取る列挙子ポインタ
);

例えば、オペレーティングシステム情報を取得するには次のように呼び出す。

IEnumWbemClassObject* pEnumerator = NULL;
HRESULT hr = pServices->ExecQuery(
    bstr_t("WQL"),
    bstr_t("SELECT * FROM Win32_OperatingSystem"),
    WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    NULL,
    &pEnumerator
);
if (FAILED(hr)) {
    wprintf(L"Query for operating system failed. Error code = 0x%X\n", hr);
}

7. 結果の列挙 (IEnumWbemClassObject::Next)

クエリ結果からオブジェクトを1件ずつ取得する。

HRESULT IEnumWbemClassObject::Next(
    LONG lTimeout,                  // タイムアウト(WBEM_INFINITE は無制限)
    ULONG uCount,                   // 取得するオブジェクト数(通常 1)
    IWbemClassObject **apObjects,   // 取得したオブジェクト配列
    ULONG *puReturned               // 実際に返された数
);

例えば、Win32_OperatingSystemCaption プロパティを列挙するには次のように呼び出す。

IWbemClassObject *pObj = NULL;
ULONG uReturn = 0;

while (pEnumerator) {
    HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pObj, &uReturn);
    if (0 == uReturn) break;

    VARIANT vtProp;
    pObj->Get(L"Caption", 0, &vtProp, 0, 0);
    wprintf(L"OS Name : %s\n", vtProp.bstrVal);
    VariantClear(&vtProp);
    pObj->Release();
}
pEnumerator->Release();

8. 後処理 (Release / CoUninitialize)

使用したCOMオブジェクトを解放し、COMライブラリをアンロードする。

// IWbemServices, IWbemLocator などを解放
pServices->Release();
pLocator->Release();

// COMライブラリをアンロード
CoUninitialize();

オブジェクトの操作

WMIでは、IWbemServices を介してクラスやインスタンスに対して操作を行う。代表的なものは以下の通り。

  • ExecQuery : クエリで複数インスタンスを取得
  • GetObject : 単一のクラスまたはインスタンスを取得
  • PutInstance : インスタンスを更新または作成
  • DeleteInstance : インスタンスを削除
  • ExecMethod : メソッドを呼び出す

複数のインスタンスを取得する (ExecQuery)

ExecQuery は、WQL (WMI Query Language) を使って条件に一致するオブジェクトを列挙する。

HRESULT IWbemServices::ExecQuery(
    const BSTR strQueryLanguage,    // クエリ言語(通常は "WQL")
    const BSTR strQuery,            // WQLクエリ文字列(例: "SELECT * FROM Win32_Process")
    long lFlags,                    // 実行フラグ(例: WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY)
    IWbemContext *pCtx,             // コンテキスト情報(通常 NULL)
    IEnumWbemClassObject **ppEnum   // 結果を受け取る列挙子ポインタ
);

例えば、現在のオペレーティングシステム情報を取得するには、次のように呼び出す。

IEnumWbemClassObject* pEnumerator = NULL;
HRESULT hr = pServices->ExecQuery(
    bstr_t("WQL"),
    bstr_t("SELECT * FROM Win32_OperatingSystem"),
    WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
    NULL,
    &pEnumerator
);

if (SUCCEEDED(hr)) {
    IWbemClassObject* pObj = NULL;
    ULONG uReturn = 0;

    while (pEnumerator) {
        hr = pEnumerator->Next(WBEM_INFINITE, 1, &pObj, &uReturn);
        if (0 == uReturn) break;

        VARIANT vtProp;
        pObj->Get(L"Caption", 0, &vtProp, 0, 0);
        wprintf(L"OS Name : %s\n", vtProp.bstrVal);
        VariantClear(&vtProp);
        pObj->Release();
    }
    pEnumerator->Release();
}

単一のインスタンスを取得する (GetObject)

GetObject は、オブジェクトパスを指定して単一のWMIインスタンスを取得する。

HRESULT IWbemServices::GetObject(
    const BSTR strObjectPath,       // オブジェクトパス(例: "Win32_Process.Handle='1234'")
    long lFlags,                    // フラグ(通常 0)
    IWbemContext *pCtx,             // コンテキスト情報(通常 NULL)
    IWbemClassObject **ppObject,    // 取得したオブジェクトの出力
    IWbemCallResult **ppCallResult  // 非同期結果(同期なら NULL)
);

例えば、シングルトンである Win32_OperatingSystem のインスタンスを取得するには

IWbemClassObject* pObj = NULL;
HRESULT hr = pServices->GetObject(
    _bstr_t(L"Win32_OperatingSystem=@"), // シングルトンは '@' でアクセス
    0,
    NULL,
    &pObj,
    NULL
);

if (SUCCEEDED(hr)) {
    VARIANT vtProp;
    pObj->Get(L"Caption", 0, &vtProp, 0, 0);
    wprintf(L"OS Name: %s\n", vtProp.bstrVal);
    VariantClear(&vtProp);
    pObj->Release();
}

インスタンスを更新または作成する (PutInstance)

PutInstance は、既存のインスタンスを更新するか、新しいインスタンスを作成する。

HRESULT IWbemServices::PutInstance(
    IWbemClassObject *pInst,        // 更新または作成するインスタンス
    long lFlags,                    // 操作フラグ(WBEM_FLAG_UPDATE_ONLY / WBEM_FLAG_CREATE_ONLY / WBEM_FLAG_CREATE_OR_UPDATE)
    IWbemContext *pCtx,             // コンテキスト情報(通常 NULL)
    IWbemCallResult **ppCallResult  // 非同期呼び出し時の結果(通常 NULL)
);

例えば、コンピュータ名を変更するには次のように呼び出す。なお、実行には管理者権限が必要になる。

IWbemClassObject* pObj = NULL;
HRESULT hr = pServices->GetObject(
    _bstr_t(L"Win32_ComputerSystem.Name='MYPC'"),
    0,
    NULL,
    &pObj,
    NULL
);

if (SUCCEEDED(hr)) {
    VARIANT vtProp;
    VariantInit(&vtProp);
    vtProp.vt = VT_BSTR;
    vtProp.bstrVal = SysAllocString(L"NEW_NAME");
    pObj->Put(L"Name", 0, &vtProp, 0);
    VariantClear(&vtProp);

    pServices->PutInstance(pObj, WBEM_FLAG_UPDATE_ONLY, NULL, NULL);
    pObj->Release();
}

インスタンスを削除する (DeleteInstance)

DeleteInstance は、オブジェクトパスを指定して該当インスタンスを削除する。

HRESULT IWbemServices::DeleteInstance(
    const BSTR strObjectPath,       // インスタンスのオブジェクトパス
    long lFlags,                    // フラグ(通常 0)
    IWbemContext *pCtx,             // コンテキスト情報(通常 NULL)
    IWbemCallResult **ppCallResult  // 非同期呼び出し時の結果(通常 NULL)
);

例えば、特定のプロセス (PID=1234) を終了するには、次のように呼び出す。

HRESULT hr = pServices->DeleteInstance(
    _bstr_t(L"Win32_Process.Handle='1234'"), // PID=1234 のプロセス
    0,
    NULL,
    NULL
);

if (SUCCEEDED(hr)) {
    wprintf(L"Process terminated.\n");
}

メソッドを呼び出す (ExecMethod)

ExecMethod は、クラスやインスタンスに対してメソッドを実行する。

HRESULT IWbemServices::ExecMethod(
    const BSTR strObjectPath,        // メソッドを呼び出す対象(クラスまたはインスタンスのパス)
    const BSTR strMethodName,        // メソッド名
    long lFlags,                     // フラグ(通常 0)
    IWbemContext *pCtx,              // コンテキスト情報(通常 NULL)
    IWbemClassObject *pInParams,     // 入力パラメータ(NULL可)
    IWbemClassObject **ppOutParams,  // 出力パラメータ(結果)
    IWbemCallResult **ppCallResult   // 非同期呼び出し時の結果(通常 NULL)
);

例えば、Win32_Process クラスの Create メソッドで notepad.exe を起動するには、次のように呼び出す。

IWbemClassObject* pClass = NULL;
pServices->GetObject(_bstr_t(L"Win32_Process"), 0, NULL, &pClass, NULL);

IWbemClassObject* pInParamsDefinition = NULL;
pClass->GetMethod(L"Create", 0, &pInParamsDefinition, NULL);

IWbemClassObject* pInParams = NULL;
pInParamsDefinition->SpawnInstance(0, &pInParams);

VARIANT vtProp;
VariantInit(&vtProp);
vtProp.vt = VT_BSTR;
vtProp.bstrVal = SysAllocString(L"notepad.exe");
pInParams->Put(L"CommandLine", 0, &vtProp, 0);
VariantClear(&vtProp);

IWbemClassObject* pOutParams = NULL;
HRESULT hr = pServices->ExecMethod(
    _bstr_t(L"Win32_Process"),
    _bstr_t(L"Create"),
    0,
    NULL,
    pInParams,
    &pOutParams,
    NULL
);

if (SUCCEEDED(hr)) {
    wprintf(L"Process created successfully.\n");
}

pInParams->Release();
pInParamsDefinition->Release();
pClass->Release();
pOutParams->Release();