今回は、PowerShellのGet-WinEventコマンドレットを使ってWindowsイベントログを効率的に解析する方法を、実際の運用シナリオとともに解説します。
Windows Serverの障害調査や監査対応において、イベントログの読み取りは避けて通れない作業です。GUIのイベントビューアーでも確認できますが、大量のログから目的のイベントを絞り込むには限界があります。Get-WinEventを使いこなすことで、数万件のログから必要な情報を瞬時に抽出できるようになります。
Get-WinEventとGet-EventLogの違い
Windowsのイベントログ取得コマンドにはGet-EventLogとGet-WinEventの2種類があります。現場では今でもGet-EventLogを使っているケースを見かけますが、Windows Vista以降のログ形式(Evtx)にはGet-WinEventを使うべき理由があります。
| 比較項目 | Get-EventLog | Get-WinEvent |
|---|---|---|
| 対応ログ形式 | 従来のクラシックログのみ | クラシック + EVTXログ(全対応) |
| フィルタ速度 | 低速(全件取得後にフィルタ) | 高速(カーネルレベルでフィルタ) |
| リモート対応 | 限定的 | Invoke-Command併用で完全対応 |
| 廃止予定 | あり(PowerShell 6以降非対応) | 今後もサポート継続 |
Get-EventLogはPowerShell Core(6以降)では使用できません。将来性を考えてもGet-WinEventへの移行を推奨します。
基本的な使い方とフィルタリング
# システムログの最新100件を取得
Get-WinEvent -LogName System -MaxEvents 100
# セキュリティログからエラーと警告を取得
Get-WinEvent -LogName Security -MaxEvents 50 |
Where-Object { $_.LevelDisplayName -in @("エラー", "警告") }
# 利用可能なログ名の一覧を確認
Get-WinEvent -ListLog * | Where-Object { $_.RecordCount -gt 0 } |
Select-Object LogName, RecordCount | Sort-Object RecordCount -Descending
Where-Objectでのフィルタは全件取得後の絞り込みになるため、ログ量が多い場合は次に紹介するFilterHashtableを使いましょう。
FilterHashtableで高速絞り込み
-FilterHashtableパラメータを使うと、ログの読み込み時点でフィルタリングが行われるため、大幅に処理が高速化されます。
# 過去24時間のシステムエラーを取得
$filter = @{
LogName = 'System'
Level = 2 # 2=エラー, 3=警告, 4=情報
StartTime = (Get-Date).AddHours(-24)
}
Get-WinEvent -FilterHashtable $filter
# 特定のイベントIDで絞り込む(ログオン失敗: 4625)
$secFilter = @{
LogName = 'Security'
Id = 4625
StartTime = (Get-Date).AddDays(-7)
}
Get-WinEvent -FilterHashtable $secFilter |
Select-Object TimeCreated, Message |
Format-List
Levelの対応表:
| 値 | レベル |
|---|---|
| 1 | 重大 |
| 2 | エラー |
| 3 | 警告 |
| 4 | 情報 |
| 5 | 詳細 |
XMLクエリによる高度なフィルタリング
さらに細かい条件で絞り込むには、-FilterXmlまたは-FilterXPathを使います。イベントビューアーのGUIでフィルタを作成し、XMLを確認してコピーする方法が実用的です。
# XPathクエリで特定ユーザーのログオン失敗を抽出
$xpath = @"
*[System[EventID=4625] and EventData[Data[@Name='TargetUserName']='administrator']]
"@
Get-WinEvent -LogName Security -FilterXPath $xpath |
Select-Object TimeCreated, @{N='Message';E={$_.Message}} |
Format-List
# 複数のイベントIDをOR条件で指定
$multiIdXPath = "*[System[(EventID=4624 or EventID=4625 or EventID=4634)]]"
Get-WinEvent -LogName Security -FilterXPath $multiIdXPath -MaxEvents 200
よく使う運用シナリオ別スクリプト
シナリオ1:ログオン失敗の連続発生を検出
# 過去1時間のログオン失敗を集計(ブルートフォース検知)
$startTime = (Get-Date).AddHours(-1)
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625; StartTime=$startTime} |
ForEach-Object {
$xml = [xml]$_.ToXml()
[PSCustomObject]@{
Time = $_.TimeCreated
UserName = $xml.Event.EventData.Data | Where-Object {$_.Name -eq 'TargetUserName'} | Select-Object -ExpandProperty '#text'
SourceIP = $xml.Event.EventData.Data | Where-Object {$_.Name -eq 'IpAddress'} | Select-Object -ExpandProperty '#text'
}
} |
Group-Object SourceIP |
Sort-Object Count -Descending |
Select-Object Count, Name
シナリオ2:サービス停止イベントのCSV出力
# サービス停止(7034)と予期しない再起動(6008)を収集
$events = Get-WinEvent -FilterHashtable @{
LogName = 'System'
Id = @(7034, 6008)
StartTime = (Get-Date).AddDays(-30)
}
$events | Select-Object TimeCreated, Id, LevelDisplayName, Message |
Export-Csv -Path "C:\work\ServiceEvents.csv" -Encoding UTF8 -NoTypeInformation
シナリオ3:リモートサーバーのログを一括収集
# 複数サーバーのシステムエラーを一括収集
$servers = @("SRV01", "SRV02", "SRV03")
$results = @()
foreach ($server in $servers) {
try {
$events = Get-WinEvent -ComputerName $server -FilterHashtable @{
LogName = 'System'
Level = 2
StartTime = (Get-Date).AddDays(-1)
} -ErrorAction Stop
$results += $events | Select-Object @{N='Server';E={$server}}, TimeCreated, Id, Message
}
catch {
Write-Warning "[$server] 取得失敗: $($_.Exception.Message)"
}
}
$results | Export-Csv -Path "C:\work\AllServerErrors.csv" -Encoding UTF8 -NoTypeInformation
実務でハマりやすいポイント
① セキュリティログのアクセス権限
セキュリティログは管理者権限がないと読み取れません。Get-WinEvent -LogName Securityを実行して「アクセスが拒否されました」が出る場合は、PowerShellを「管理者として実行」してください。
② リモートアクセス時のWinRM設定
-ComputerNameオプションでリモートサーバーに接続するには、対象サーバーでWinRMが有効になっている必要があります。
# 対象サーバーでWinRMを有効化(管理者権限が必要)
Enable-PSRemoting -Force
③ 大量ログで処理が重い場合
-MaxEventsで取得件数を制限しつつ、FilterHashtableのStartTime/EndTimeで期間を絞ることが重要です。Where-Objectだけに頼ると全件取得になり、何万件ものログで数分待たされることがあります。
まとめ
Get-WinEventは、Windowsイベントログ解析の中核となる強力なコマンドレットです。本記事のポイントをまとめます。
- Get-EventLogからの移行:EVTXログ対応・高速フィルタ・将来性の観点でGet-WinEventを使う
- FilterHashtableの活用:ログ読み込み段階でフィルタして処理を高速化する
- シナリオ別スクリプトの整備:ログオン失敗監視・サービス異常検知などを定型化しておく
イベントログの解析を自動化することで、障害対応のスピードが大幅に向上します。まずはFilterHashtableを使ったログ取得から始めて、XPathクエリへと段階的にスキルアップしていきましょう。
