ROLE: シニアPowerShellエンジニア(Windows/Linux運用エキスパート)
LANGUAGE: 日本語(専門用語は正確に、解説は簡潔かつロジカルに)
TECH-STACK: PowerShell 7.x (Core) & 5.1 (Desktop), CIM Cmdlets, WS-Man, .NET Core/Framework
FOCUS: CIMインスタンスを用いた非同期取得、WS-Manプロトコルの最適化、大規模環境でのスケーラビリティ
POLICY: Get-WmiObjectを廃止し、DCOM/WS-Man両対応のCIMコマンドレットを推奨。エラーハンドリングは具体的に記述。 本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
CIM/WMIを活用した分散端末の状態監視・イベントログ集約自動化
【導入:解決する課題】
リモートPCの稼働状況と致命的エラーを一括取得し、管理者が手動で行っていた巡回点検工数を最小化します。
【設計方針と処理フロー】
本スクリプトでは、旧来の Get-WmiObject (DCOM依存) を避け、最新の Get-CimInstance (WS-Man対応) を採用します。これにより、ファイアウォール親和性を高め、PS 7.x 環境での ForEach-Object -Parallel による高速な並列処理を実現します。
graph TD
A[Start] --> B["Target Computer List"]
B --> C{"Test Connection"}
C -->|Online| D["Parallel CIM Session"]
C -->|Offline| E["Log Offline Status"]
D --> F["Query OS/CPU/Disk Info"]
F --> G["Fetch Error Event Logs"]
G --> H["Standardize Objects"]
H --> I["Export JSON/CSV"]
I --> J[Finish]
【実装:コアスクリプト】
以下は、並列処理(PowerShell 7以降推奨)と厳格なエラー制御を組み込んだ監視スクリプトのプロトタイプです。
function Get-RemoteSystemHealth {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string[]]$ComputerName,
[Parameter()]
[int]$MaxConcurrency = 10,
[Parameter()]
[int]$EventLogLimit = 5
)
process {
$results = $ComputerName | ForEach-Object -Parallel {
$comp = $_
$report = [PSCustomObject]@{
Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
ComputerName = $comp
Status = "Success"
OSCaption = $null
CpuUsage = $null
FreeDiskGB = $null
RecentErrors = @()
ErrorMessage = $null
}
try {
# 接続確認 (Timeout 2s)
if (-not (Test-Connection -ComputerName $comp -Count 1 -Quiet)) {
throw "Node unreachable."
}
# CIMセッションのオプション設定 (WS-Man)
$sessionOption = New-CimSessionOption -Protocol Wsman
$session = New-CimSession -ComputerName $comp -SessionOption $sessionOption -ErrorAction Stop
# システム情報の取得
$os = Get-CimInstance -CimSession $session -ClassName Win32_OperatingSystem
$report.OSCaption = $os.Caption
# ディスク空き容量 (Cドライブのみ抽出)
$disk = Get-CimInstance -CimSession $session -ClassName Win32_LogicalDisk -Filter "DeviceID='C:'"
$report.FreeDiskGB = [math]::Round($disk.FreeSpace / 1GB, 2)
# CPU使用率 (直近値)
$cpu = Get-CimInstance -CimSession $session -ClassName Win32_Processor
$report.CpuUsage = $cpu.LoadPercentage
# イベントログの取得 (SystemログのErrorレベルを抽出)
$errors = Get-WinEvent -ComputerName $comp -LogName System -MaxEvents $using:EventLogLimit `
-FilterHashtable @{Level=2} -ErrorAction SilentlyContinue
if ($errors) {
$report.RecentErrors = $errors | ForEach-Object { $_.Message.Trim() }
}
Remove-CimSession $session
}
catch {
$report.Status = "Failed"
$report.ErrorMessage = $_.Exception.Message
}
return $report
} -ThrottleLimit $MaxConcurrency
return $results
}
}
# 実行例
# $targets = Get-Content "./server_list.txt"
# Get-RemoteSystemHealth -ComputerName $targets | ConvertTo-Json | Out-File "./report.json"
【検証とパフォーマンス評価】
計測方法:
Measure-Command { Get-RemoteSystemHealth -ComputerName (1..50) }を実行。期待値:
ForEach-Object -Parallelを使用しない場合、50台のシーケンシャル処理で約5〜10分を要するが、並列度10の設定では1分前後(ネットワーク遅延に依存)まで短縮可能。スケーラビリティ:
MaxConcurrencyを調整することで、コア数に応じた最適化が可能。
【運用上の落とし穴と対策】
WinRMの未構成: CIM/WS-Manを利用するため、対象側で
Enable-PSRemotingが必須。拒否される場合は GPO での「Windows リモート管理」の許可が必要。PowerShell 5.1との互換性: 上記スクリプトの
-Parallelスイッチは PowerShell 7 専用。5.1 環境ではStart-JobまたはWorkflow(非推奨) への書き換えが必要。文字化け (Encoding):
Get-WinEventのメッセージに含まれる日本語が化ける場合、出力時にOut-File -Encoding utf8を明示すること(PS 7は既定でUTF-8)。ダブルホップ問題: リモートPCからさらに別のサーバーのリソースを触る場合、CredSSP または Kerberos 委任の設定が必要。
【まとめ】
CIMへの移行:
Get-WmiObjectを捨て、ファイアウォール対応が容易なGet-CimInstanceを標準とする。並列化の活用: 大規模環境では
ForEach-Object -Parallelでスループットを向上させる。例外の構造化:
try/catchを用い、オフライン端末があっても全体の処理を止めない堅牢なコードを記述する。

コメント