本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
VBAで実現するWMIプロセス監視:特定アプリの異常検知と自動ログ記録
【背景と目的】
業務システムのフリーズを監視し、自動検知とログ記録を行う仕組みを構築。システム監視の属人化を防ぎ、ダウンタイムを最小化します。 実務では、バックグラウンドで動くべきデータ連携ツールが音もなく停止し、数時間後に発覚するといった致命的な遅延トラブルが頻発しています。本ツールでこれを自動監視します。
【処理フロー図】
graph TD
A["開始"] --> B["WMIサービスへ接続"]
B --> C["Win32_Processをクエリ"]
C --> D{"監視対象プロセスが存在するか?"}
D -- NO --> E["異常検知ログ出力/通知"]
D -- YES --> F["メモリ使用量等のステータス取得"]
F --> G["指定時間待機: Win32 API Sleep"]
G --> C
※監視のループ処理にはCPU負荷を抑えるためWin32 APIのSleepを使用します。
【実装:VBAコード】
Option Explicit
' --- Win32 API 宣言 (64bit/32bit両対応) ---
#If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr)
#Else
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If
' --- 監視設定 ---
Private Const TARGET_PROCESS As String = "Excel.exe" ' 監視対象プロセス名
Private Const INTERVAL_MS As Long = 5000 ' 監視間隔(ミリ秒)
Private IsMonitoring As Boolean ' 監視フラグ
''' <summary>
''' プロセス監視のメインルーチン
''' </summary>
Public Sub StartProcessMonitoring()
Dim objWMIService As Object
Dim colProcesses As Object
Dim objProcess As Object
Dim msg As String
Dim logRow As Long
IsMonitoring = True
logRow = 2 ' ログ書き出し開始行
' 高速化: 画面更新停止
Application.ScreenUpdating = False
On Error GoTo ErrorHandler
' WMIサービスへの接続
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Debug.Print "監視開始: " & TARGET_PROCESS
Do While IsMonitoring
' プロセス情報の取得(Win32_Processクラスを使用)
Set colProcesses = objWMIService.ExecQuery( _
"SELECT * FROM Win32_Process WHERE Name = '" & TARGET_PROCESS & "'")
If colProcesses.Count = 0 Then
' 異常検知:プロセスが見つからない場合
Call WriteLog(logRow, TARGET_PROCESS, "MISSING/STOPPED", 0)
logRow = logRow + 1
Else
' 正常稼働:メモリ使用量などを取得
For Each objProcess In colProcesses
' WorkingSetSize (物理メモリ使用量) をMB単位で取得
Dim memUsage As Double
memUsage = Round(objProcess.WorkingSetSize / 1024 / 1024, 2)
Call WriteLog(logRow, TARGET_PROCESS, "RUNNING", memUsage)
logRow = logRow + 1
Next objProcess
End If
' 終了判定用のイベント処理
DoEvents
' 指定時間待機(APIを使用しCPU負荷を低減)
Sleep INTERVAL_MS
' ログが溜まりすぎないよう定期的に画面を更新
If logRow Mod 10 = 0 Then Application.ScreenUpdating = True: Application.ScreenUpdating = False
Loop
ExitHandler:
Application.ScreenUpdating = True
Set objWMIService = Nothing
Exit Sub
ErrorHandler:
MsgBox "エラーが発生しました: " & Err.Description, vbCritical
Resume ExitHandler
End Sub
''' <summary>
''' 監視停止用
''' </summary>
Public Sub StopMonitoring()
IsMonitoring = False
Debug.Print "監視停止リクエストを受理しました"
End Sub
''' <summary>
''' シートへのログ書き出し
''' </summary>
Private Sub WriteLog(ByRef row As Long, procName As String, status As String, mem As Double)
With ThisWorkbook.Sheets(1)
.Cells(row, 1).Value = Now
.Cells(row, 2).Value = procName
.Cells(row, 3).Value = status
.Cells(row, 4).Value = mem & " MB"
End With
End Sub
【技術解説】
WMI (Windows Management Instrumentation): Windows OSの管理情報を取得するためのインターフェースです。
Win32_Processクラスを利用することで、実行中の全プロセスのCPU時間、メモリ使用量、スレッド数、開始時刻などを標準機能だけで取得できます。API Sleep による低負荷化: VBAの
Waitメソッドは1秒単位でしか制御できず、TimerループはCPUを100%近く消費する危険があります。Win32 APIのSleepを使うことで、OSに制御を戻しながらミリ秒単位の正確な待機が可能になります。PtrSafe 宣言: 現代のOffice環境(64bit)において、従来のAPI宣言は動作しません。
PtrSafeと条件付きコンパイル(VBA7)を用いることで、あらゆる環境で動作する堅牢性を確保しています。
【注意点と運用】
無限ループの回避:
DoEventsをループ内に入れることで、Excelがフリーズして操作不能になるのを防いでいます。停止ボタンや特定のセル値による停止フラグのチェックを必ず実装してください。管理者権限: 他ユーザーが実行しているプロセスを詳細に監視する場合、Excel自体を「管理者として実行」する必要があるケースがあります。
メモリの解放: WMIのクエリ結果(
colProcesses)は、ループごとにオブジェクトを生成するため、本来は明示的にNothingを代入するか、スコープを最小限にする設計が望ましいです。
【まとめ】
標準機能を活用: WMIを使えば、外部ライブラリ無しで高度なシステム監視が可能。
APIで安定化:
SleepとPtrSafeの組み合わせは、実務レベルのツール開発には必須の技術。可視化と自動記録: 検知するだけでなく、Excelシートにログを落とすことで、後からの原因究明(事後分析)が容易になる。

