LoginSignup
2
2

More than 5 years have passed since last update.

JScriptでWMI(その4)

Posted at

はじめに

「JScriptでWMI」も今回で4回目となりました。
こんなに、長くやる予定はなかったのですが、それなりにネタがあったのが驚きです。

今回は、イベントについてです。

個人的には、挙動がイマイチわかりづらいので、あまり利用しません。

イベント待ち合わせ

「ExecNotificationQuery」メソッドを利用して、「SWbemEventSource」オブジェクトを取得し、「NextEvent」メソッドでイベントを待ち合わせを行います。

まずは、サンプルです。

// クエリ設定
var query = "SELECT * FROM __InstanceCreationEvent WITHIN 5"
        + " WHERE TargetInstance ISA 'Win32_Process'"
        + " AND TargetInstance.Name = 'notepad.exe'";

// 「SWbemLocator」オブジェクト取得
var locator = new ActiveXObject("WbemScripting.SWbemLocator");
// 「SWbemServices」オブジェクト取得(ローカルコンピュータ、名前空間「root\CIMV2」)
var services = locator.ConnectServer(null, "root\\CIMV2");
// 「SWbemEventSource」オブジェクト取得
var eventSource = services.ExecNotificationQuery(query);

// 無限ループ
while (true) {
    // イベント待ち
    var event = eventSource.NextEvent();
    // インスタンス取得
    var object = event.TargetInstance;
    // インスタンス存在チェック
    if (object != null) {
        // イベント結果
        WScript.Echo("Event:" + event.Path_.Class + ",ProcessId=" + object.ProcessId + ",Name=" + object.Name);
    }
}

「ExecQuery」メソッドと同じようにクエリ(WQL)を設定しますが、構文がだいぶ異なります。

FROM句に、イベントの種類__InstanceCreationEventと、監視間隔WITHIN 5
WHERE句に、インスタンスの指定TargetInstance ISA 'Win32_Process'と、条件TargetInstance.Name = 'notepad.exe'
を指定します。

サンプルコードでは、「Win32_Process」クラスの「Name」が「notepad.exe」の物を、5秒間隔「WITHIN 5」で作られたら「__InstanceCreationEvent」イベントとして受信する。
といったクエリとなります。

監視間隔時間内に「notepad.exe」を起動→終了した場合は検知されません。

イベントの種類として、良く使うものを表にします。

クラス名 説明
__InstanceOperationEvent __InstanceCreationEvent
__InstanceModificationEvent
__InstanceDeletionEvent
全て
__InstanceCreationEvent インスタンスの追加時
__InstanceModificationEvent インスタンスの変更時
__InstanceDeletionEvent インスタンスの削除時

プロセスを監視したい場合

プロセスの追加、削除イベントを待ち合わせたい場合のサンプルコードです。

// クエリ設定
var query = "SELECT * FROM __InstanceOperationEvent WITHIN 5"
        + " WHERE TargetInstance ISA 'Win32_Process'"
        + " AND TargetInstance.Name = 'notepad.exe'";

// 「SWbemLocator」オブジェクト取得
var locator = new ActiveXObject("WbemScripting.SWbemLocator");
// 「SWbemServices」オブジェクト取得(ローカルコンピュータ、名前空間「root\CIMV2」)
var services = locator.ConnectServer(null, "root\\CIMV2");
// 「SWbemEventSource」オブジェクト取得
var eventSource = services.ExecNotificationQuery(query);

// 無限ループ
while (true) {
    // イベント待ち
    var event = eventSource.NextEvent();
    // インスタンス取得
    var object = event.TargetInstance;
    // インスタンス存在チェック
    if (object != null) {
        // イベント種類判定
        if (event.Path_.Class == "__InstanceCreationEvent"
            || event.Path_.Class == "__InstanceDeletionEvent") {
            // イベント結果
            WScript.Echo("Event:" + event.Path_.Class
                + ",ProcessId=" + object.ProcessId + ",Name=" + object.Name);
        }
    }
}

イベントの種類は__InstanceOperationEventで、追加、変更、削除といづれの場合にも受信します。

イベント種類判定処理で、イベントクラスが__InstanceCreationEventと`__InstanceDeletionEventだけイベント結果を出力しています。

サービスを監視したい場合

サービスの変更イベントを受信するサンプルです。
監視間隔を10秒としています。

// クエリ設定
var query = "SELECT * FROM __InstanceModificationEvent WITHIN 10"
        + " WHERE TargetInstance ISA 'Win32_Service'"
        + " AND TargetInstance.Name = 'wuauserv'";

// 「SWbemLocator」オブジェクト取得
var locator = new ActiveXObject("WbemScripting.SWbemLocator");
// 「SWbemServices」オブジェクト取得(ローカルコンピュータ、名前空間「root\CIMV2」)
var services = locator.ConnectServer(null, "root\\CIMV2");
// 「SWbemEventSource」オブジェクト取得
var eventSource = services.ExecNotificationQuery(query);

// 無限ループ
while (true) {
    // イベント待ち
    var event = eventSource.NextEvent();
    // インスタンス取得
    var object = event.TargetInstance;
    // インスタンス存在チェック
    if (object != null) {
        // イベント結果
        WScript.Echo("Event:" + event.Path_.Class
            + ",State=" + object.State + ",Name=" + object.Name);
    }
}

その他のイベント待ち合わせ

いままで「InstanceOperationEvent」「InstanceCreationEvent」「InstanceModificationEvent」「InstanceDeletionEvent」などを利用していましたが、他にもイベント待ちのWMIクラスがあります。

その内の一つ、プロセス監視を使ってみます。

クラス名 説明
Win32_ProcessTrace Win32_ProcessStartTrace
Win32_ProcessStopTrace
全て
Win32_ProcessStartTrace プロセス追加
Win32_ProcessStartTrace プロセス削除
// クエリ設定
var query = "SELECT * FROM Win32_ProcessTrace WHERE ProcessName = 'notepad.exe'";

// 「SWbemLocator」オブジェクト取得
var locator = new ActiveXObject("WbemScripting.SWbemLocator");
// 「SWbemServices」オブジェクト取得(ローカルコンピュータ、名前空間「root\CIMV2」)
var services = locator.ConnectServer(null, "root\\CIMV2");
// 「SWbemEventSource」オブジェクト取得
var eventSource = services.ExecNotificationQuery(query);

// 無限ループ
while (true) {
    // イベント待ち
    var event = eventSource.NextEvent();
    // イベント結果
    WScript.Echo("Event:" + event.Path_.Class
        + ",ProcessId=" + event.ProcessID
        + ",Name=" + event.ProcessName);
}

インスタンスが取得出来るわけではなく、イベントのプロパティのみ使えます。
このサンプルの場合「Win32_ProcessTrace」を利用しているので「Win32_ProcessStartTrace」「Win32_ProcessStopTrace」両方のイベントを待ち合わせます。

懸念点

冒頭にも書きましたが、個人的にあまり利用しません。
その大きな理由は以下の二点です。

  • 間隔指定なので、取りこぼす場合がある
    (だったら、自前でポーリングする)
  • プロセスの正常な終了方法がわからない
    (リソースが宙ぶらりんにならないか心配)
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2