【実務・中級編】【WMI非同期クエリ】ExecNotificationQuery を用いたファイル作成・プロセス起動イベントのリアルタイム監視 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

VBScriptの極致:ポーリングを捨て、WMIイベント駆動でシステムを掌握せよ

業務自動化の現場でよく見かける「Sleepループ」。1秒おきにファイルを確認し、CPUを無駄に回し、システムを疲弊させるあの非効率なやり方は、今日で卒業だ。

Windowsの世界には、システムが何らかの事象(イベント)を発生させた瞬間にスクリプトを呼び出す「WMI非同期クエリ(ExecNotificationQuery)」という強力な武器がある。これを使えば、CPU負荷0で、かつリアルタイムにプロセスの起動やファイルの作成を検知できる。

今回は、真に堅牢な「イベント駆動型」監視スクリプトの書き方を伝授する。

なぜ「Sleepループ」が愚策なのか

多くの初心者は `Do…Loop` の中に `WScript.Sleep 1000` を入れ、`If FSO.FileExists(…)` を繰り返す。しかし、これには致命的な欠陥がある。

1. タイムラグ: 1秒のSleepなら、平均0.5秒の検知遅延が発生する。
2. リソース浪費: 監視中、スクリプトは常にアクティブであり、無駄なI/Oを発生させる。
3. 競合リスク: ファイル書き込みの途中で検知してしまい、アクセス拒否エラーを誘発する。

WMIイベントサブスクリプションは、OSのカーネルレベルの通知をフックする。OSが「イベントが発生した」と告げるまで、スクリプトは完全に静止(待機)しているため、システム負荷は皆無だ。

実装:プロセス起動監視のプロダクションコード

まずは、特定のプロセス(例:`notepad.exe`)が起動した瞬間に検知する汎用的なコードを見てほしい。

‘ — WMIイベント監視:プロセス起動検知 —
Option Explicit

Dim objWMIService, colEvents, objEvent
Dim strQuery

‘ WMIのローカル接続
Set objWMIService = GetObject(“winmgmts:\\.\root\cimv2”)

‘ プロセス生成を監視するWQLクエリ
‘ __InstanceCreationEvent は生成イベントを指す
strQuery = “SELECT FROM __InstanceCreationEvent WITHIN 5 ” & _
“WHERE TargetInstance ISA ‘Win32_Process’ ” & _
“AND TargetInstance.Name = ‘notepad.exe'”

‘ 非同期受信用のイベントコンシューマを作成
Set colEvents = objWMIService.ExecNotificationQuery(strQuery)

WScript.Echo “監視を開始しました。Notepadを起動してください…”

Do
‘ 次のイベントが来るまで、ここでスレッドが完全に停止する(CPU負荷0)
Set objEvent = colEvents.NextEvent

‘ イベント発生!
WScript.Echo “検知: ” & objEvent.TargetInstance.Name & ” が起動しました。”
WScript.Echo “PID: ” & objEvent.TargetInstance.ProcessId

‘ ここに後続処理(DB連携、ファイル書き込み等)を記述する
Loop

堅牢な設計のための「3つの鉄則」

現場でそのまま動かし続けるためには、以下の設計思想が不可欠だ。

1. `WITHIN` 句の適切な設定

WQL内の `WITHIN 5` はポーリング間隔ではなく、イベントの「グループ化ウィンドウ」を意味する。値を小さくしすぎるとOS側の負荷が増し、大きくしすぎると通知が遅れる。プロセスの場合は5〜10秒が妥当だ。

2. エラーハンドリングの徹底

WMIクエリは、WMIリポジトリの破損や権限の問題で突然切断されることがある。`On Error Resume Next` を駆使し、ループ内で `Err.Number` をチェックする構造にすべきだ。切断されたら再接続する「自己復帰ロジック」を組み込むのがプロの仕事である。

3. ファイル監視の罠(FileSystemWatcherの代替)

ファイル監視(`__InstanceCreationEvent` を `CIM_DataFile` に対して実行)を行う場合、書き込み完了までのラグを考慮せよ。ファイルが作成された瞬間に `OpenTextFile` を叩くと、書き込み中による「Permission Denied」が発生する。検知後に数ミリ秒の待機を入れるか、ファイルサイズが安定するまでリトライする処理が必須だ。

次なるステップへ

このアーキテクチャを理解すれば、あなたの自動化ツールは「単なるプログラム」から「システムの一部」へと進化する。

  • ログ連携: `WScript.Echo` の代わりに `FileSystemObject` でCSVに書き込み、BIツールで可視化する。
  • 通知連携: 検知した瞬間に PowerShell を呼び出し、Microsoft Teams や Slack の Webhook へ JSON を飛ばす。

VBScriptは古臭い言語だと言われることもある。だが、OSの深淵(WMI)を直接叩けるこの言語は、Windows自動化における「最も鋭利なナイフ」だ。このナイフを正しく使いこなし、泥臭いポーリング作業から自分自身を解放してほしい。

コードは、常にシンプルで、かつ「沈黙」を恐れないものにする。それが、一流のエンジニアの流儀だ。

タイトルとURLをコピーしました