VBAで実現するWMIプロセス監視:特定アプリの異常検知と自動ログ記録

Tech

本記事は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

【技術解説】

  1. WMI (Windows Management Instrumentation): Windows OSの管理情報を取得するためのインターフェースです。Win32_Process クラスを利用することで、実行中の全プロセスのCPU時間、メモリ使用量、スレッド数、開始時刻などを標準機能だけで取得できます。

  2. API Sleep による低負荷化: VBAの Wait メソッドは1秒単位でしか制御できず、Timer ループはCPUを100%近く消費する危険があります。Win32 APIの Sleep を使うことで、OSに制御を戻しながらミリ秒単位の正確な待機が可能になります。

  3. PtrSafe 宣言: 現代のOffice環境(64bit)において、従来のAPI宣言は動作しません。PtrSafe と条件付きコンパイル(VBA7)を用いることで、あらゆる環境で動作する堅牢性を確保しています。

【注意点と運用】

  • 無限ループの回避: DoEvents をループ内に入れることで、Excelがフリーズして操作不能になるのを防いでいます。停止ボタンや特定のセル値による停止フラグのチェックを必ず実装してください。

  • 管理者権限: 他ユーザーが実行しているプロセスを詳細に監視する場合、Excel自体を「管理者として実行」する必要があるケースがあります。

  • メモリの解放: WMIのクエリ結果(colProcesses)は、ループごとにオブジェクトを生成するため、本来は明示的にNothingを代入するか、スコープを最小限にする設計が望ましいです。

【まとめ】

  1. 標準機能を活用: WMIを使えば、外部ライブラリ無しで高度なシステム監視が可能。

  2. APIで安定化: SleepPtrSafe の組み合わせは、実務レベルのツール開発には必須の技術。

  3. 可視化と自動記録: 検知するだけでなく、Excelシートにログを落とすことで、後からの原因究明(事後分析)が容易になる。

ライセンス:本記事のテキスト/コードは特記なき限り CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。

コメント

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