【VBA×WMI】Windowsプロセス監視とメモリ・増殖異常を自動検知する仕組みの構築

Tech

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

【VBA×WMI】Windowsプロセス監視とメモリ・増殖異常を自動検知する仕組みの構築

【背景と目的】

外部システムのバッチ処理や特定プロセスのフリーズ・増殖によりExcelが極端に重くなる課題を、WMIによる常時監視と異常検知で解決します。(68文字)

【処理フロー図】

graph TD
    A["監視処理の開始"] --> B["WMIでプロセス情報を取得"]
    B --> C{"メモリ使用量・個数の閾値判定"}
    C -->|異常あり| D["配列に異常データを格納"]
    C -->|正常| E["次の判定へ"]
    D --> F["シートへ一括書き出し・アラート表示"]
    E --> F
    F --> G["処理終了"]

【実装:VBAコード】

※Win32 API宣言を含め、参照設定なし(遅延結合)で動作する設計です。

Option Explicit

' --- Win32 APIの宣言 (64bit/32bit両対応) ---
#If VBA7 Then

    Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#Else

    Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If

' 監視メイン処理
Public Sub MonitorWindowsProcesses()
    On Error GoTo ErrorHandler

    ' 高速化設定
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    Application.EnableEvents = False

    ' 監視設定(例: メモリ使用量が200MB以上のプロセス、または特定のプロセス名)
    Const MEMORY_THRESHOLD_MB As Double = 200.0
    Const TARGET_PROCESS_NAME As String = "excel.exe"

    ' WMIオブジェクトのバインド(遅延結合)
    Dim wmiService As Object
    Set wmiService = GetObject("winmgmts:\\.\root\cimv2")

    ' プロセス一覧のクエリ実行
    Dim processList As Object
    Set processList = wmiService.ExecQuery("SELECT * FROM Win32_Process")

    ' ログ出力用配列の準備 (最大1000行 x 4列)
    Dim logData() As Variant
    ReDim logData(1 To 1000, 1 To 4)
    Dim logIndex As Long: logIndex = 0

    Dim proc As Object
    Dim memUsageMB As Double
    Dim procCount As Long: procCount = 0

    ' プロセスループ
    For Each proc In processList
        ' メモリ使用量(WorkingSetSize)の算出 (Byte -> MB)
        If Not IsNull(proc.WorkingSetSize) Then
            memUsageMB = CDbl(proc.WorkingSetSize) / 1024 / 1024
        Else
            memUsageMB = 0
        End If

        ' 同一プロセスの個数カウント
        If LCase(proc.Name) = LCase(TARGET_PROCESS_NAME) Then
            procCount = procCount + 1
        End If

        ' 異常条件判定(指定メモリ超え、またはターゲットプロセスの監視)
        If memUsageMB > MEMORY_THRESHOLD_MB Or LCase(proc.Name) = LCase(TARGET_PROCESS_NAME) Then
            logIndex = logIndex + 1
            If logIndex <= UBound(logData, 1) Then
                logData(logIndex, 1) = Now                          ' 検知日時
                logData(logIndex, 2) = proc.Name                    ' プロセス名
                logData(logIndex, 3) = proc.ProcessId               ' PID
                logData(logIndex, 4) = Round(memUsageMB, 2) & " MB" ' メモリ使用量
            End If
        End If
    Next proc

    ' ワークシートへの一括書き出し処理
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Sheets(1)

    ' 見出しの設定
    ws.Range("A1:D1").Value = Array("検知日時", "プロセス名", "PID", "メモリ使用量")

    ' 既存データのクリアと一括出力
    If logIndex > 0 Then
        ws.Range("A2:D1001").ClearContents
        ws.Range("A2").Resize(logIndex, 4).Value = logData

        MsgBox "監視完了: " & logIndex & " 件の対象プロセスを検出しました。" & vbCrLf & _
               TARGET_PROCESS_NAME & " の起動数: " & procCount & " 個", vbInformation, "プロセス監視完了"
    Else
        MsgBox "異常プロセスは検出されませんでした。", vbInformation, "プロセス監視完了"
    End If

CleanUp:
    ' 設定のリストア
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic
    Application.EnableEvents = True
    Set wmiService = Nothing
    Set processList = Nothing
    Exit Sub

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

【技術解説】

  • WMI (Win32_Process) の活用: GetObject("winmgmts:\\.\root\cimv2") を使用することで、外部参照設定を追加することなく遅延結合でローカル環境のシステムプロセス情報へアクセスしています。

  • 配列を活用した超高速出力: セルへ1行ずつ書き込むと描画オーバーヘッドが大きく処理速度が低下します。そのため、VBA内部の2次元配列 logData に結果を集約し、Resize メソッドで一括書き出しを行っています。

  • 64bit互換のWin32 API宣言: 今回は直接使用していませんが、定期監視ループなどで待機を入れる場合を想定し、PtrSafe キーワードを使用した Sleep API 宣言を含めています。

【注意点と運用】

  • 権限の問題: 実行するユーザーアカウントの権限(管理者権限の有無)によっては、一部のシステムプロセス情報(WorkingSetSize 等)が取得できず Null を返す場合があります。IsNull チェックで実行時エラーを防止してください。

  • WMIクエリのオーバーヘッド: ExecQuery("SELECT * FROM Win32_Process") は強力ですが、高頻度(数秒置き等)で実行するとVBA自体のCPU使用率が上昇します。一定の間隔(数分置き等)での定期実行にとどめてください。

【まとめ】

  1. WMI×遅延結合で環境に依存しないプロセス監視を実現する。

  2. 2次元配列による一括出力で、監視ログ書き込みの処理負荷を最小化する。

  3. API宣言はPtrSafeを徹底し、64bit Office環境での安全性を確保する。

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

コメント

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