WMI/CIMを活用したリモートPC一括監視とイベントログ抽出の自動化

PowerShellカテゴリを表すパンダのイラスト PowerShell

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

WMI/CIMを活用したリモートPC一括監視とイベントログ抽出の自動化

【導入:解決する課題】

数百台規模のリモートPCに対する手動のヘルスチェックを廃止し、OSの状態と特定エラーログをエージェントレスで高速に自動収集します。

【設計方針と処理フロー】

通信効率とセキュリティの観点から、レガシーなDCOM(WMI)ではなく、WS-Managementプロトコルを使用するCIMコマンドレット(Get-CimInstance)をベースに構築します。また、大規模環境での実行速度を確保するため、PowerShell 7.xの並列処理(ForEach-Object -Parallel)を採用します。

graph TD
A[Start] --> B["コンピューターリストの読み込み"]
B --> C{"並列処理開始"}
C --> D["CIMセッションの確立試行"]
D -->|Success| E["OS情報/稼働時間の取得"]
E --> F["特定イベントログの抽出"]
F --> G["CIMセッションの破棄"]
D -->|Failure| H["エラーログ記録"]
G --> I["結果をカスタムオブジェクトに統合"]
H --> I
I --> J{"全ホスト終了?"}
J -->|Yes| K["CSV/JSONレポート出力"]
K --> L[Finish]

【実装:コアスクリプト】

以下は、リモート端末からOS情報(稼働時間含む)と、直近24時間のSystemログから「Error」を抽出する実戦的なスクリプトです。

function Get-RemoteSystemHealth {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string[]]$ComputerNames,

        [Parameter()]
        [int]$MaxConcurrency = 10
    )

    # 並列処理によるデータ収集(PowerShell 7+ 推奨)

    $Results = $ComputerNames | ForEach-Object -Parallel {
        $Computer = $_
        $ErrorActionPreference = "Stop"

        $Report = [PSCustomObject]@{
            Timestamp    = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
            ComputerName = $Computer
            OSCaption    = $null
            LastBootUp   = $null
            UptimeDays   = $null
            ErrorLogs    = $null
            Status       = "Success"
            ErrorMessage = $null
        }

        try {

            # CIMオプションの設定(DCOMフォールバックが必要な場合はここで定義)

            $Option = New-CimSessionOption -Protocol Wsman -ConnectTimeoutSec 10
            $Session = New-CimSession -ComputerName $Computer -Option $Option

            # 1. OS基本情報と稼働時間の取得

            $OsInfo = Get-CimInstance -CimSession $Session -ClassName Win32_OperatingSystem
            $Report.OSCaption = $OsInfo.Caption
            $Report.LastBootUp = $OsInfo.LastBootUpTime
            $Report.UptimeDays = [Math]::Round(((Get-Date) - $OsInfo.LastBootUpTime).TotalDays, 2)

            # 2. 直近24時間のエラーイベント取得(Systemログ)

            $FilterTime = (Get-Date).AddDays(-1)
            $Events = Get-CimInstance -CimSession $Session -ClassName Win32_NTLogEvent `
                -Filter "Logfile='System' AND Type='Error' AND TimeGenerated >= '$($FilterTime.ToString('yyyyMMddHHmmss.000000-000'))'"

            $Report.ErrorLogs = ($Events | ForEach-Object { "ID:$($_.EventCode) Source:$($_.SourceName)" }) -join " | "

            Remove-CimSession $Session
        }
        catch {
            $Report.Status = "Failed"
            $Report.ErrorMessage = $_.Exception.Message
        }
        finally {
            $Report
        }
    } -ThrottleLimit $MaxConcurrency

    return $Results
}

# --- 実行例 ---


# $TargetList = Get-Content "C:\temp\PCList.txt"


# $HealthReport = Get-RemoteSystemHealth -ComputerNames $TargetList


# $HealthReport | Export-Csv -Path "./SystemHealthReport.csv" -NoTypeInformation -Encoding utf8

【検証とパフォーマンス評価】

100台のリモートPCに対して実行する場合、逐次処理(Sequential)ではネットワークタイムアウト待ちを含め数十分を要しますが、上記スクリプトの並列処理(-Parallel)を用いることで大幅に短縮可能です。

  • 計測例: Measure-Command { Get-RemoteSystemHealth -ComputerNames $testList }

  • 期待値: スロットル制限(MaxConcurrency)を適切に設定することで、逐次処理比で3倍〜5倍の高速化が期待できます。ただし、送信元PCのメモリ消費量と、ネットワーク帯域の飽和に注意が必要です。

【運用上の落とし穴と対策】

  1. WinRMの有効化とFirewall: リモートPC側で Enable-PSRemoting が実行されており、TCP 5985 (HTTP) / 5986 (HTTPS) が許可されている必要があります。

  2. PowerShell 5.1 vs 7: ForEach-Object -Parallel は PowerShell 7 固有の機能です。Windows PowerShell 5.1 環境では Start-JobRunspaces を使用した書き換えが必要になります。

  3. ダブルホップ問題: リモートPCからさらに別のサーバーのリソースにアクセスする場合、Kerberos認証の委任設定(CredSSP等)が必要になります。今回のCIM取得のみであれば通常は不要です。

  4. WMIクエリのタイムアウト: イベントログが肥大化している場合、Win32_NTLogEvent へのクエリがタイムアウトすることがあります。-Filter 句で TimeGenerated をインデックスに基づき絞り込むことが必須です。

【まとめ】

  1. CIMコマンドレットを優先: DCOMに依存する Get-WmiObject ではなく、Firewallフレンドリーな Get-CimInstance を使用すること。

  2. 並列処理の最適化: ネットワークの遅延時間を吸収するため、ForEach-Object -Parallel で同時接続数を制御しながら実行すること。

  3. 例外処理の徹底: 接続失敗やタイムアウトを Try-Catch で捕捉し、処理全体を止めないロギング戦略を構築すること。

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

コメント

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