本記事は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のメモリ消費量と、ネットワーク帯域の飽和に注意が必要です。
【運用上の落とし穴と対策】
WinRMの有効化とFirewall: リモートPC側で
Enable-PSRemotingが実行されており、TCP 5985 (HTTP) / 5986 (HTTPS) が許可されている必要があります。PowerShell 5.1 vs 7:
ForEach-Object -Parallelは PowerShell 7 固有の機能です。Windows PowerShell 5.1 環境ではStart-JobやRunspacesを使用した書き換えが必要になります。ダブルホップ問題: リモートPCからさらに別のサーバーのリソースにアクセスする場合、Kerberos認証の委任設定(CredSSP等)が必要になります。今回のCIM取得のみであれば通常は不要です。
WMIクエリのタイムアウト: イベントログが肥大化している場合、
Win32_NTLogEventへのクエリがタイムアウトすることがあります。-Filter句でTimeGeneratedをインデックスに基づき絞り込むことが必須です。
【まとめ】
CIMコマンドレットを優先: DCOMに依存する
Get-WmiObjectではなく、FirewallフレンドリーなGet-CimInstanceを使用すること。並列処理の最適化: ネットワークの遅延時間を吸収するため、
ForEach-Object -Parallelで同時接続数を制御しながら実行すること。例外処理の徹底: 接続失敗やタイムアウトを
Try-Catchで捕捉し、処理全体を止めないロギング戦略を構築すること。


コメント