[META:STYLE_PS_ENGINEER] 本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
WMI/CIMを活用したマルチノード並列ヘルスチェック・自動モニタリング
【導入:解決する課題】 多数のリモートPCに対するOS状態確認とエラーログ収集を並列化し、管理者の巡回コストを最小化します。
【設計方針と処理フロー】
標準のCIMコマンドレット(WS-Managementプロトコル)を採用し、DCOM依存の古いWMIコマンドレットを排除します。処理の高速化のため、PowerShell 7の-Parallelパラメータを利用した並列実行設計を行います。
graph TD
A["PCリスト読み込み"] --> B["CIMセッションの確立"]
B --> C{"並列処理実行"}
C --> D["システム情報取得: Win32_OperatingSystem"]
C --> E["リソース監視: Win32_LogicalDisk"]
C --> F["イベントログ収集: Win32_NTLogEvent"]
D --> G["カスタムオブジェクト生成"]
E --> G
F --> G
G --> H["CSV/JSON出力・ログ記録"]
【実装:コアスクリプト】
function Get-RemoteSystemHealth {
<#
.SYNOPSIS
複数のリモートPCからシステム状態とエラーイベントを取得します。
.DESCRIPTION
CIMセッションを使用して、CPU、メモリ、ディスク、直近のエラーログを並列で取得します。
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string[]]$ComputerNames,
[int]$MaxConcurrency = 10,
[int]$ErrorLogDays = 1
)
$results = $ComputerNames | ForEach-Object -Parallel {
$computer = $_
$logPath = "C:\Temp\HealthCheck_Log.txt" # 簡易ログパス
try {
# CIMオプションの設定(接続タイムアウト対策)
$option = New-CimSessionOption -Protocol Wsman -ConnectTimeoutSec 5
$session = New-CimSession -ComputerName $computer -SessionOption $option -ErrorAction Stop
# 1. OS情報の取得 (ホスト名、OS、メモリ)
$os = Get-CimInstance -CimSession $session -ClassName Win32_OperatingSystem
# 2. ディスク空き容量の取得 (Cドライブ)
$disk = Get-CimInstance -CimSession $session -ClassName Win32_LogicalDisk -Filter "DeviceID='C:'"
# 3. イベントログの取得 (直近X日のErrorレベルのみ)
$filterDate = (Get-Date).AddDays(-$using:ErrorLogDays)
$events = Get-CimInstance -CimSession $session -ClassName Win32_NTLogEvent `
-Filter "Type='Error' AND TimeGenerated > '$($filterDate.ToString('yyyyMMddHHmmss.ffffff-000'))'"
# 結果の集約
[PSCustomObject]@{
ComputerName = $computer
Status = "Online"
OSCaption = $os.Caption
FreeMemoryGB = [Math]::Round($os.FreePhysicalMemory / 1MB, 2)
DiskFreeGB = [Math]::Round($disk.FreeSpace / 1GB, 2)
ErrorCount = ($events | Measure-Object).Count
Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
}
}
catch {
Write-Error "Failed to query $computer : $($_.Exception.Message)"
[PSCustomObject]@{
ComputerName = $computer
Status = "Offline/Error"
OSCaption = $null
FreeMemoryGB = 0
DiskFreeGB = 0
ErrorCount = -1
Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
}
}
finally {
if ($session) { Remove-CimSession $session }
}
} -ThrottleLimit $MaxConcurrency
return $results
}
# 実行例
# $targets = Get-Content "C:\nodes.txt"
# Get-RemoteSystemHealth -ComputerNames $targets | Export-Csv -Path "./HealthReport.csv" -NoTypeInformation -Encoding utf8
【検証とパフォーマンス評価】
計測手法:
Measure-Command { Get-RemoteSystemHealth -ComputerNames (1..50 | % { "PC-$_" }) }を使用。期待値:
逐次処理(PS 5.1)の場合:1台あたり約3〜5秒(計150秒以上)。
並列処理(PS 7.4)の場合:スロットル制限10並列で、ネットワーク遅延を含め約20〜30秒で完了。
リソース消費: CIMセッションはRPC/DCOMより軽量ですが、大量のイベントログ取得はリモート側のWMIサービスに負荷をかけるため、フィルタリング条件(
Filter句)の最適化が必須です。
【運用上の落とし穴と対策】
WinRMの有効化: リモートPC側で
Enable-PSRemotingが実行されている必要があります。ワークグループ環境ではTrustedHostsの設定も不可欠です。PS 5.1 vs 7 互換性:
-Parallelスイッチは PowerShell 7 以降の機能です。Windows PowerShell 5.1 を維持する必要がある場合は、Workflow(非推奨)ではなくStart-JobやRunspacesを検討してください。WMIクエリのタイムアウト:
Win32_NTLogEventは件数が多いと非常に低速です。必ずTimeGeneratedによるフィルタリングを行い、取得件数を絞ってください。文字コード:
Export-Csvを行う際は、Excelでの閲覧を考慮して-Encoding utf8(BOM付き) またはunicodeを指定してください。
【まとめ】
CIMコマンドレットを優先: DCOM(135)ではなくWS-Man(5985)を使用し、モダンな管理インフラを構築する。
サーバー側でフィルタリング: データを全取得してから抽出するのではなく、
Filter句を使用してリモート側で計算させる。並列化による時短:
ForEach-Object -Parallelを活用し、監視窓口のブロッキングを最小限に抑える。

コメント