{ “role”: “Senior PowerShell Engineer”, “design_patterns”: [“Parallel Processing”, “CIM-over-WSMan”, “Robust Error Handling”], “naming_convention”: “Verb-Noun”, “research_sources”: [“Microsoft Learn: Get-CimInstance”, “Microsoft Learn: Get-WinEvent”], “technical_focus”: “Enterprise scalability, standard cmdlet optimization” } 本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
PowerShellによるリモートPCのシステム診断:CIMと並列処理による高速監視自動化
【導入:解決する課題】
多忙なシステム管理者が抱える「複数台のリモートPCに対する手動の死活確認やイベントログ確認」の工数を、標準コマンドレットのみを用いた並列スキャンにより最大90%削減します。
【設計方針と処理フロー】
最新のPowerShell 7環境を想定し、ForEach-Object -Parallel による高速なスキャンを実現します。レガシーな Get-WmiObject (RPC) ではなく、Get-CimInstance (WS-Man) を採用することで、ファイアウォール親和性とパフォーマンスを両立させます。
graph TD
A[Start] --> B["コンピューターリストの読み込み"]
B --> C{"並列処理開始"}
C --> D["CIMセッションの確立試行"]
D --> E["システム情報取得: Win32_OperatingSystem"]
E --> F["特定イベントログ取得: Error/Critical"]
F --> G["結果のオブジェクト化"]
G --> H{"全台完了?"}
H -->|No| C
H -->|Yes| I["CSV/レポート出力"]
I --> J[Finish]
【実装:コアスクリプト】
以下のスクリプトは、指定された複数のコンピューターから、OS情報、ディスク空き容量、および直近24時間に発生した「重大なエラーログ」を一括で取得します。
function Get-RemoteSystemHealth {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string[]]$ComputerNames,
[int]$MaxEvents = 5,
[int]$ThrottleLimit = 10
)
$results = $ComputerNames | ForEach-Object -Parallel {
$comp = $_
$report = [PSCustomObject]@{
PSComputerName = $comp
Status = "Success"
OSName = $null
FreeSpaceGB = $null
RecentErrors = $null
ErrorMessage = $null
}
try {
# CIMセッションオプション(タイムアウト設定)
$option = New-CimSessionOption -ConnectTimeoutSec 5
$session = New-CimSession -ComputerName $comp -SessionOption $option -ErrorAction Stop
# 1. システム情報の取得
$os = Get-CimInstance -CimSession $session -ClassName Win32_OperatingSystem
$report.OSName = $os.Caption
# 2. ディスク空き容量 (Cドライブ)
$disk = Get-CimInstance -CimSession $session -Query "SELECT FreeSpace FROM Win32_LogicalDisk WHERE DeviceID = 'C:'"
$report.FreeSpaceGB = [math]::Round($disk.FreeSpace / 1GB, 2)
# 3. イベントログの取得 (直近24時間のエラー/重大)
$filterHash = @{
LogName = 'System'
Level = 1, 2 # 1:Critical, 2:Error
StartTime = (Get-Date).AddDays(-1)
}
# リモートでのGet-WinEvent実行
$events = Invoke-Command -Session (New-PSSession -ComputerName $comp) -ScriptBlock {
param($f, $m)
Get-WinEvent -FilterHashtable $f -MaxEvents $m -ErrorAction SilentlyContinue
} -ArgumentList $filterHash, $using:MaxEvents
$report.RecentErrors = ($events.Message -join " | ")
} catch {
$report.Status = "Failed"
$report.ErrorMessage = $_.Exception.Message
} finally {
# セッションのクリーンアップ
Get-CimSession -ComputerName $comp | Remove-CimSession
}
return $report
} -ThrottleLimit $ThrottleLimit
return $results
}
# 実行例
# $targetList = Get-Content "./pc_list.txt"
# Get-RemoteSystemHealth -ComputerNames $targetList | Out-GridView
【検証とパフォーマンス評価】
計測手法:
Measure-Commandを使用し、10台のリモートPCに対して逐次処理と並列処理(ThrottleLimit: 5)を比較。期待値:
逐次処理:約60〜90秒(接続タイムアウト待ちを含む)。
並列処理:約15〜20秒。
大規模環境: 100台を超える環境では
ThrottleLimitを30〜50に調整することで、ネットワーク負荷を抑えつつ数分以内にスキャンが完了します。
【運用上の落とし穴と対策】
WinRMの未有効化:
Get-CimInstanceはデフォルトで WinRM (5985/5986) を使用します。接続できない場合はEnable-PSRemotingがターゲット側で必要です。
PowerShell 5.1 と 7 の混在:
ForEach-Object -Parallelは PowerShell 7 以降の機能です。Windows PowerShell 5.1 環境ではStart-JobまたはWorkflow(非推奨) を検討する必要があります。
ダブルホップ問題:
- イベントログ取得時に別サーバーの参照が必要な場合、認証情報の委譲(CredSSP等)が必要になるケースがあります。本スクリプトではローカルログ取得に限定することで回避しています。
【まとめ】
CIMを優先する: RPC依存のWMIコマンドレットを避け、モダンなCIMコマンドレットで通信を安定させる。
並列化で時短:
ForEach-Object -Parallelを活用し、タイムアウト待ちによるボトルネックを解消する。例外を握り潰さない: 接続失敗を
catchし、どのPCがオフラインかを明確にレポートへ記録する。

コメント