VBA×WMI:特定業務プロセスの生存監視とメモリ異常検知の自動化

Tech

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

VBA×WMI:特定業務プロセスの生存監視とメモリ異常検知の自動化

【背景と目的】

基幹システムのフリーズや予期せぬ終了によるデータ損失を防ぐため、WMIを用いてプロセスの動作状況とメモリ使用量をリアルタイムで監視する仕組みを構築します。

【処理フロー図】

graph TD
A["開始"] --> B["WMIオブジェクトの初期化"]
B --> C["対象プロセスのクエリ実行"]
C --> D{"プロセスは存在するか?"}
D -- No --> E["異常検知アラート/ログ記録"]
D -- Yes --> F["メモリ使用量の取得"]
F --> G{"閾値を超過しているか?"}
G -- Yes --> H["警告フラグ設定"]
G -- No --> I["正常ステータス記録"]
H --> J["Excelシートへ一括書き出し"]
I --> J
J --> K["待機(Sleep)"]
K --> C

【実装:VBAコード】

Option Explicit

' 64bit/32bit両対応のSleep宣言
#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

' 監視設定定数
Private Const TARGET_PROCESS As String = "Excel.exe" ' 監視対象プロセス名
Private Const MEM_THRESHOLD_MB As Double = 500      ' 異常検知メモリ閾値(MB)
Private Const INTERVAL_MS As Long = 5000            ' 監視間隔(ミリ秒)

Sub StartProcessMonitoring()
    Dim objWMIService As Object
    Dim colProcesses As Object
    Dim objProcess As Object
    Dim ws As Worksheet
    Dim lastRow As Long
    Dim results(1 To 1, 1 To 4) As Variant ' 高速化のため配列を使用

    Set ws = ThisWorkbook.Sheets(1)

    ' 初期描画抑制
    Application.ScreenUpdating = False

    On Error Resume Next
    ' WMIサービスへの接続
    Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
    On Error GoTo 0

    If objWMIService Is Nothing Then
        MsgBox "WMIの初期化に失敗しました。", vbCritical
        Exit Sub
    End If

    Debug.Print "監視を開始します... (Ctrl+Pauseで停止)"

    Do
        ' プロセス情報の取得(WQL)
        Set colProcesses = objWMIService.ExecQuery _
            ("SELECT * FROM Win32_Process WHERE Name = '" & TARGET_PROCESS & "'")

        lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row + 1

        If colProcesses.Count = 0 Then
            ' プロセスが見つからない場合
            results(1, 1) = Now
            results(1, 2) = TARGET_PROCESS
            results(1, 3) = "未検出"
            results(1, 4) = "CRITICAL: プロセスが停止しています"
            ws.Cells(lastRow, 1).Resize(1, 4).Value = results
        Else
            For Each objProcess In colProcesses
                Dim memUsage As Double
                memUsage = Round(objProcess.WorkingSetSize / 1024 / 1024, 2) ' MB換算

                results(1, 1) = Now
                results(1, 2) = objProcess.Name & " (ID:" & objProcess.ProcessId & ")"
                results(1, 3) = memUsage & " MB"

                If memUsage > MEM_THRESHOLD_MB Then
                    results(1, 4) = "WARNING: メモリ使用量過多"
                Else
                    results(1, 4) = "正常"
                End If

                ' 配列からシートへ一括書き込み(高速化)
                ws.Cells(lastRow, 1).Resize(1, 4).Value = results
                lastRow = lastRow + 1
            Next
        End If

        ' バッファのクリアと待機
        DoEvents
        Sleep INTERVAL_MS

        ' 無限ループ対策(特定のセルが空でなければ継続など、運用に合わせて調整)
        If ws.Range("Z1").Value = "STOP" Then Exit Do
    Loop

    Application.ScreenUpdating = True
    MsgBox "監視を終了しました。", vbInformation
End Sub

【技術解説】

  1. WMI (Windows Management Instrumentation): Windows OSの管理情報を取得する業界標準インターフェースです。Win32_Process クラスを使用することで、実行中のプロセス名、ID、メモリ使用量(WorkingSetSize)などをSQLライクな構文(WQL)で抽出できます。

  2. PtrSafe Sleep: VBA標準の Wait メソッドは1秒単位でしか制御できず、かつExcel全体をフリーズさせるため、Win32 APIの Sleep を使用してミリ秒単位の制御とCPU負荷の抑制を行っています。

  3. 配列による書き出し: ループ内で直接セルに書き込むのではなく、一旦配列(results)に格納してからシートへ一括出力することで、画面更新負荷を最小化しています。

【注意点と運用】

  • 参照設定不要: GetObject を使用する実行時バインディング(Late Binding)を採用しているため、配布時の参照設定トラブルを回避しています。

  • 無限ループの停止: DoEvents を挟むことで実行中のExcel操作を可能にしていますが、強制終了用に「特定のセルにSTOPと入力されたら終了」などの脱出フラグを設けることが実務上不可欠です。

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

【まとめ】

  1. WMIを活用すれば、外部ツールなしでWindowsプロセスの死活監視が可能。

  2. Sleep APIと配列処理の組み合わせにより、Excelのパフォーマンス低下を防ぐ。

  3. 異常検知時のログ出力を自動化することで、システムトラブルの早期発見に貢献する。

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

コメント

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