VBAで実現するWMIプロセス監視:特定アプリの暴走とリソース枯渇の自動検知

Tech

本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。

VBAで実現するWMIプロセス監視:特定アプリの暴走とリソース枯渇の自動検知

【背景と目的】

外部連携ソフトのフリーズや、VBA実行中のメモリリークによるPC停止を未然に防ぐため、WMIを用いてOSのプロセス負荷を監視し、異常時に警告を発します。

【処理フロー図】

graph TD
A["開始"] --> B["WMIサービスへ接続"]
B --> C["特定プロセスのリソース取得"]
C --> D{"閾値を超過しているか?"}
D -- Yes --> E["異常検知ログの書き出し"]
D -- No --> F["正常終了/待機"]
E --> G["指定プロセスの強制終了検討"]
G --> H["終了"]
F --> H

【実装:VBAコード】

Option Explicit

' --- Win32 API 宣言 (64bit環境対応) ---
#If Win64 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

''' <summary>
''' 指定したプロセスのCPU使用率とメモリ使用量を監視し、Excelシートへ記録する
''' </summary>
Public Sub MonitorProcessPerformance()
    Dim strComputer As String: strComputer = "."
    Dim strProcessName As String: strProcessName = "Excel.exe" ' 監視対象プロセス名
    Dim objWMIService As Object
    Dim colProcesses As Object
    Dim objProcess As Object
    Dim results() As Variant
    Dim i As Long: i = 1

    ' 描画停止による高速化
    Application.ScreenUpdating = False

    On Error GoTo ErrorHandler

    ' WMIサービスへの接続
    Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

    ' プロセス情報の取得 (Win32_PerfFormattedData_PerfProc_Process を使用して計算済み負荷を取得)
    Set colProcesses = objWMIService.ExecQuery( _
        "SELECT * FROM Win32_PerfFormattedData_PerfProc_Process WHERE Name = '" & Left(strProcessName, InStrRev(strProcessName, ".") - 1) & "'")

    ' 結果格納用の配列準備 (行: 項目, 列: データ)
    ReDim results(1 To 2, 1 To 4)
    results(1, 1) = "プロセス名"
    results(1, 2) = "CPU使用率(%)"
    results(1, 3) = "メモリ使用量(MB)"
    results(1, 4) = "取得時刻"

    For Each objProcess In colProcesses
        i = i + 1
        ReDim Preserve results(1 To 2, 1 To i)
        results(2, 1) = objProcess.Name
        results(2, 2) = objProcess.PercentProcessorTime
        results(2, 3) = Round(objProcess.WorkingSetPrivate / 1024 / 1024, 2) ' Byte -> MB
        results(2, 4) = Now

        ' 異常検知ロジック (例: CPU 90%以上 または メモリ 1GB以上)
        If objProcess.PercentProcessorTime > 90 Or (objProcess.WorkingSetPrivate / 1024 / 1024) > 1024 Then
            MsgBox "警告: " & objProcess.Name & " の負荷が閾値を超えました。", vbCritical
        End If
    Next

    ' シートへの一括書き出し (セルへの個別アクセスを避けて高速化)
    If i > 1 Then
        Range("A1").Resize(UBound(results, 2), UBound(results, 1)).Value = Application.Transpose(results)
    Else
        Debug.Print "対象プロセスが見つかりませんでした。"
    End If

CleanUp:
    Set colProcesses = Nothing
    Set objWMIService = Nothing
    Application.ScreenUpdating = True
    Exit Sub

ErrorHandler:
    MsgBox "エラーが発生しました: " & Err.Description, vbExclamation
    Resume CleanUp
End Sub

【技術解説】

  1. WMI (Windows Management Instrumentation): Windowsのシステム情報を取得するための標準インターフェースです。今回は Win32_PerfFormattedData_PerfProc_Process クラスを利用し、OS側で計算済みのCPU使用率を直接取得しています(手動計算不要)。

  2. PtrSafe 宣言: Sleep などの API を使用する場合、64bit Office環境でのクラッシュを防ぐために必須の記述です。

  3. 配列による一括出力: セルに対してループ内で書き込みを行うと極端に動作が重くなるため、一度配列に格納してから Resize メソッドで一括出力しています。

【注意点と運用】

  • WMIの負荷: WMIクエリは強力ですが、頻繁(1秒未満の間隔など)に実行すると、監視自体がCPUリソースを消費します。監視間隔は5秒〜1分程度を推奨します。

  • 権限の問題: 他ユーザーのプロセス情報を取得する場合、Excelを「管理者として実行」する必要がある場合があります。

  • プロセス名の指定: Win32_PerfFormattedData クラスでは、拡張子(.exe)を除いた名前を指定する必要がある点に注意してください。

【まとめ】

  • WMIを活用することで、VBAからOSレベルのリソース監視が容易になる。

  • 配列処理とAPIの適切な宣言(PtrSafe)により、高速かつ安定したツールが構築可能。

  • 異常検知時はメッセージボックスだけでなく、ログファイルへの追記や自動メール送信へ拡張するのが実用的。

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

コメント

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