VBAとWMIを用いたWindowsプロセス監視と異常検知の自動化

Tech

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

VBAとWMIを用いたWindowsプロセス監視と異常検知の自動化

【背景と目的】 基幹システムのフリーズや特定アプリのメモリ異常消費を早期発見し、業務停止リスクを最小化します。手動監視を自動化し、ログ記録までを一貫して行います。(67文字)

【処理フロー図】

graph TD
A["監視メイン処理開始"] --> B["WMI接続確立"]
B --> C["Win32_Processから情報取得"]
C --> D{"特定プロセスの稼働確認"}
D -- 未起動 --> E["異常ログ記録/通知"]
D -- 稼働中 --> F["メモリ使用量等の閾値判定"]
F -- 閾値超過 --> G["強制終了または警告"]
F -- 正常 --> H["処理終了/待機"]
G --> 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

' プロセス監視マクロ
' 参照設定不要(実行時バインディング)
Sub WatchSpecificProcess()
    Dim wmiService As Object
    Dim processes As Object
    Dim process As Object
    Dim targetProcessName As String
    Dim thresholdMemoryMB As Double
    Dim isFound As Boolean
    Dim logSheet As Worksheet
    Dim lastRow As Long

    ' --- 設定項目 ---
    targetProcessName = "Excel.exe" ' 監視対象プロセス名
    thresholdMemoryMB = 500         ' メモリ閾値 (MB)
    Set logSheet = ThisWorkbook.Sheets(1)

    ' 高速化設定
    Application.ScreenUpdating = False

    On Error GoTo ErrorHandler

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

    ' 実行中のプロセス一覧を取得
    Set processes = wmiService.ExecQuery("SELECT * FROM Win32_Process WHERE Name = '" & targetProcessName & "'")

    isFound = False
    For Each process In processes
        isFound = True
        ' WorkingSetSize (バイト) を MB に変換
        Dim memUsageMB As Double
        memUsageMB = Round(CDbl(process.WorkingSetSize) / 1024 / 1024, 2)

        ' 異常検知:メモリ使用量が閾値を超えている場合
        If memUsageMB > thresholdMemoryMB Then
            Call WriteLog(logSheet, targetProcessName, "警告:メモリ過多 (" & memUsageMB & " MB)")
            ' 必要に応じて process.Terminate で強制終了させることも可能
        End If
    Next process

    ' 異常検知:プロセスが見つからない場合
    If Not isFound Then
        Call WriteLog(logSheet, targetProcessName, "異常:プロセス未検出")
    End If

CleanUp:
    Application.ScreenUpdating = True
    Set processes = Nothing
    Set wmiService = Nothing
    Exit Sub

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

' ログ記録用サブ関数
Private Sub WriteLog(ws As Worksheet, procName As String, message As String)
    Dim nextRow As Long
    nextRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row + 1

    ' 配列を用いて一括書き込み(高速化)
    Dim logData(1 To 1, 1 To 3) As Variant
    logData(1, 1) = Now
    logData(1, 2) = procName
    logData(1, 3) = message

    ws.Cells(nextRow, 1).Resize(1, 3).Value = logData
End Sub

【技術解説】

  1. WMI (Windows Management Instrumentation): 外部ライブラリの参照設定(DLL登録)なしで、OS内部のプロセス情報やハードウェアステータスにアクセスできる強力なインターフェースです。

  2. 実行時バインディング: CreateObjectGetObject を使用することで、異なるバージョンのOffice間でも参照エラーを回避し、配布性を高めています。

  3. 高速化技術: ログ出力の際、セル一つずつに書き込むのではなく、配列に格納してから Resize プロパティを用いて一括出力することで、I/O負荷を軽減しています。

  4. Win32 API: PtrSafe 宣言により、32bit/64bit双方のExcel環境で安全に動作するように設計されています。

【注意点と運用】

  • 管理者権限: WMIによる他ユーザーのプロセス情報の取得には、管理者権限が必要な場合があります。

  • 監視間隔: Sleep APIなどで無限ループさせる場合、CPU負荷を下げるために適切な待機時間(例:60,000ms = 1分)を設けてください。

  • 例外処理: ネットワーク経由でリモートPCを監視する場合、タイムアウト設定や接続エラー時の再試行ロジックの実装が推奨されます。

【まとめ】

  • WMIを活用することで、OSレベルの監視機能をVBAだけで簡単に実装可能。

  • PtrSafe 対応の API 宣言により、モダンなビジネス環境(64bit)でも安定稼働。

  • ログの配列処理等、細かな高速化が大規模な監視データ蓄積時のストレスを軽減。

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

コメント

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