今回は、Windows Server管理者やシステム運用担当者に向けて、PowerShellを使ったイベントログの効率的な収集と分析方法について解説します。
日々の運用業務やトラブルシューティングにおいて、膨大なイベントログから必要な情報を素早く抽出することは重要なスキルです。
本記事では、Get-WinEventコマンドを使った基本的な操作から実践的なフィルタリング技術、複数サーバーからの一括収集まで、実務で即座に活用できる方法を体系的にまとめました。
前提条件と対象環境
本記事で紹介するGet-WinEventコマンドは、Windows Server 2008以降のすべてのバージョンで利用可能です。Windows Server 2012以降の環境での使用を推奨します。Get-WinEventは従来のGet-EventLogコマンドの後継として開発され、より高速で詳細なログ取得が可能になっています。
基本的なGet-WinEventコマンドの使い方
PowerShellでイベントログを効率的に取得するにはGet-WinEventコマンドを使用します。このコマンドは高速かつ詳細なログ取得が可能で、すべてのイベントログに対応しています。
Get-WinEventの基本構文
# システムログを取得
Get-WinEvent -LogName System -MaxEvents 100
# アプリケーションログを取得
Get-WinEvent -LogName Application -MaxEvents 100
# 特定のイベントIDを検索
Get-WinEvent -LogName Application | Where-Object {$_.Id -eq 1000}
# 複数のログソースを同時に取得
Get-WinEvent -LogName Application,System -MaxEvents 200
# リモートサーバーのログを取得
Get-WinEvent -ComputerName Server01 -LogName System -MaxEvents 50
利用可能なログの確認
# 利用可能なログ一覧を表示
Get-WinEvent -ListLog * | Select-Object LogName, RecordCount, IsEnabled |
Where-Object {$_.RecordCount -gt 0} | Sort-Object RecordCount -Descending
主要パラメータ一覧
| パラメータ | 説明 | 使用例 |
|---|---|---|
| -LogName | ログの種類を指定 | System, Application, Security |
| -MaxEvents | 取得する最大イベント数 | -MaxEvents 100 |
| -FilterHashtable | 効率的なフィルタリング(推奨) | 後述の詳細参照 |
| -ComputerName | リモートサーバー指定 | -ComputerName Server01 |
| -Oldest | 古いイベントから取得 | -Oldest |
| -ListLog | 利用可能なログを一覧表示 | -ListLog * |
大量のログを効率的にフィルタリングする方法
数万件のログから必要な情報を素早く抽出するには、-FilterHashtableパラメータを使用します。これはパイプラインでWhere-Objectを使うよりも大幅に高速に動作します。
FilterHashtableを使った高速フィルタリング
FilterHashtableは、ハッシュテーブル形式で複数の条件を指定できる強力な機能です。
# 過去24時間のエラーログを取得
$Filter = @{
LogName = 'System'
Level = 2 # Error
StartTime = (Get-Date).AddDays(-1)
}
Get-WinEvent -FilterHashtable $Filter
# 特定のイベントIDとプロバイダーで絞り込み
$Filter = @{
LogName = 'Application'
ID = 1000, 1001, 1002
ProviderName = 'MyApplication'
StartTime = (Get-Date).AddHours(-6)
}
Get-WinEvent -FilterHashtable $Filter
# 期間を指定してエラーと警告を取得
$Filter = @{
LogName = 'System'
Level = 2, 3 # Error, Warning
StartTime = (Get-Date).AddDays(-7)
EndTime = Get-Date
}
Get-WinEvent -FilterHashtable $Filter
FilterHashtableで使用可能な主要キー
| キー | 説明 | 例 |
|---|---|---|
| LogName | ログ名(必須) | ‘System’, ‘Application’ |
| Level | イベントレベル | 1, 2, 3, 4 |
| ID | イベントID | 1000, 1001, 1002 |
| ProviderName | イベントソース | ‘Microsoft-Windows-Kernel-General’ |
| StartTime | 開始日時 | (Get-Date).AddDays(-7) |
| EndTime | 終了日時 | Get-Date |
| Keywords | イベントキーワード | 0x8000000000000000 |
Level(レベル)の値
| Level | 意味 |
|---|---|
| 1 | Critical(重大) |
| 2 | Error(エラー) |
| 3 | Warning(警告) |
| 4 | Information(情報) |
| 5 | Verbose(詳細) |
複雑な条件でのフィルタリング
FilterHashtableとパイプラインを組み合わせることで、さらに詳細な条件指定が可能です。
# FilterHashtableで大まかに絞り、Where-Objectで詳細検索
Get-WinEvent -FilterHashtable @{
LogName = 'System'
Level = 1,2,3 # Critical, Error, Warning
StartTime = (Get-Date).AddDays(-7)
} | Where-Object {$_.Message -like "*disk*"}
# 特定のイベントIDを除外
Get-WinEvent -FilterHashtable @{
LogName = 'Application'
Level = 2
StartTime = (Get-Date).AddDays(-1)
} | Where-Object {$_.Id -notin @(1000, 1001)}
複数サーバーからログを一括収集する方法
運用環境では複数のサーバーからログを集約する必要があります。リモート実行とループ処理を活用します。
複数サーバーから同時収集
# サーバーリストを定義
$Servers = @("Server01", "Server02", "Server03")
# 各サーバーからエラーログを収集
$AllLogs = foreach ($Server in $Servers) {
try {
Get-WinEvent -ComputerName $Server -FilterHashtable @{
LogName = 'System'
Level = 2
StartTime = (Get-Date).AddDays(-1)
} -ErrorAction Stop |
Select-Object @{Name='ServerName';Expression={$Server}},
TimeCreated, Id, LevelDisplayName, ProviderName, Message
}
catch {
Write-Warning "Failed to retrieve logs from $Server : $_"
}
}
# 結果を表示
$AllLogs | Format-Table -AutoSize
CSVファイルからサーバーリストを読み込む方法
# servers.csvから読み込み(列名: ServerName)
$Servers = Import-Csv -Path "C:\Scripts\servers.csv"
$Results = foreach ($Server in $Servers.ServerName) {
Get-WinEvent -ComputerName $Server -FilterHashtable @{
LogName = 'System'
Level = 2
StartTime = (Get-Date).AddDays(-1)
} -ErrorAction SilentlyContinue
}
# サーバーごとにエラー件数を集計
$Results | Group-Object MachineName |
Select-Object Name, Count |
Sort-Object Count -Descending
並列処理で高速化
PowerShell 7以降では、ForEach-Object -Parallelを使用して並列処理が可能です。
# PowerShell 7以降
$Servers = @("Server01", "Server02", "Server03")
$AllLogs = $Servers | ForEach-Object -Parallel {
Get-WinEvent -ComputerName $_ -FilterHashtable @{
LogName = 'System'
Level = 2
StartTime = (Get-Date).AddDays(-1)
} -ErrorAction SilentlyContinue
} -ThrottleLimit 5
トラブルシューティングでよく使うログ分析パターン
実務でよく遭遇するトラブルシューティングシナリオと対応するPowerShellコマンドを紹介します。
パターン1: サーバー再起動の履歴を確認
# システム起動・シャットダウンイベントを確認
Get-WinEvent -FilterHashtable @{
LogName = 'System'
ID = 1074, 6005, 6006, 6008, 6009 # シャットダウン、起動関連
StartTime = (Get-Date).AddDays(-30)
} | Select-Object TimeCreated, Id, Message |
Sort-Object TimeCreated -Descending |
Format-Table -Wrap
主要なイベントID
- 1074: ユーザーまたはアプリケーションによるシャットダウン/再起動
- 6005: イベントログサービスの開始(起動)
- 6006: イベントログサービスの停止(シャットダウン)
- 6008: 予期しないシャットダウン
- 6009: システム起動時のOSバージョン情報
パターン2: 特定のサービス障害を調査
# サービス停止・開始のイベントを検索
Get-WinEvent -FilterHashtable @{
LogName = 'System'
ID = 7034, 7035, 7036, 7040 # サービス関連イベント
StartTime = (Get-Date).AddDays(-7)
} | Where-Object {$_.Message -like "*SQL Server*"} |
Select-Object TimeCreated, Id, Message
# サービスエラーを集計
Get-WinEvent -FilterHashtable @{
LogName = 'System'
ID = 7034 # サービスの予期しない終了
StartTime = (Get-Date).AddDays(-30)
} | Group-Object {$_.Message -replace '^(.+?)\s+service.*','$1'} |
Select-Object Count, Name |
Sort-Object Count -Descending
パターン3: ディスク関連エラーの検出
# ディスクエラーを検索
Get-WinEvent -FilterHashtable @{
LogName = 'System'
ProviderName = 'Disk', 'Ntfs'
Level = 1,2,3
StartTime = (Get-Date).AddDays(-7)
} | Group-Object Id |
Select-Object Count, Name, @{Name='Sample';Expression={$_.Group[0].Message}} |
Sort-Object Count -Descending
# 特定のディスクエラー(イベントID 7, 11, 15など)を抽出
Get-WinEvent -FilterHashtable @{
LogName = 'System'
ProviderName = 'Disk'
ID = 7, 11, 15
StartTime = (Get-Date).AddDays(-7)
}
パターン4: ログオン失敗の監査
# セキュリティログからログオン失敗を抽出
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4625 # ログオン失敗
StartTime = (Get-Date).AddHours(-24)
} | Select-Object TimeCreated,
@{Name='Account';Expression={$_.Properties[5].Value}},
@{Name='SourceIP';Expression={$_.Properties[19].Value}},
@{Name='FailureReason';Expression={$_.Properties[8].Value}}
# ログオン失敗を集計
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4625
StartTime = (Get-Date).AddDays(-7)
} | Group-Object {$_.Properties[5].Value} |
Select-Object Count, Name |
Sort-Object Count -Descending
パターン5: アプリケーションエラーの分析
# アプリケーションクラッシュを検出
Get-WinEvent -FilterHashtable @{
LogName = 'Application'
ProviderName = 'Application Error', 'Windows Error Reporting'
Level = 2
StartTime = (Get-Date).AddDays(-7)
} | Select-Object TimeCreated, ProviderName, Message |
Format-List
# .NETランタイムエラーを検索
Get-WinEvent -FilterHashtable @{
LogName = 'Application'
ProviderName = '.NET Runtime'
Level = 2
StartTime = (Get-Date).AddDays(-7)
}
CSV/HTMLへのエクスポートと可視化
収集したログデータを共有可能な形式にエクスポートする方法です。
CSVファイルへのエクスポート
# システムエラーをCSVに出力
Get-WinEvent -FilterHashtable @{
LogName = 'System'
Level = 2
StartTime = (Get-Date).AddDays(-7)
} | Select-Object TimeCreated, Id, LevelDisplayName, ProviderName, Message |
Export-Csv -Path "C:\Logs\SystemErrors.csv" -NoTypeInformation -Encoding UTF8
# 複数サーバーのログを1つのCSVにまとめる
$Servers = @("Server01", "Server02", "Server03")
$AllErrors = foreach ($Server in $Servers) {
Get-WinEvent -ComputerName $Server -FilterHashtable @{
LogName = 'System'
Level = 2
StartTime = (Get-Date).AddDays(-1)
} -ErrorAction SilentlyContinue |
Select-Object @{Name='Server';Expression={$Server}}, TimeCreated, Id, Message
}
$AllErrors | Export-Csv -Path "C:\Reports\AllServers_Errors.csv" -NoTypeInformation -Encoding UTF8
HTMLレポートの作成
# HTMLレポートを生成
$Logs = Get-WinEvent -FilterHashtable @{
LogName = 'System'
Level = 1,2,3
StartTime = (Get-Date).AddDays(-1)
} | Select-Object TimeCreated, Id, LevelDisplayName, ProviderName, Message -First 100
$HTML = $Logs | ConvertTo-Html -Title "System Error Report" `
-PreContent "<h1>過去24時間のシステムログレポート</h1><p>生成日時: $(Get-Date -Format 'yyyy/MM/dd HH:mm:ss')</p>" `
-PostContent "<p>Total Events: $($Logs.Count)</p>"
$HTML | Out-File -FilePath "C:\Reports\SystemLog.html" -Encoding UTF8
グループ化して集計
# エラーをイベントID別に集計
Get-WinEvent -FilterHashtable @{
LogName = 'Application'
Level = 2
StartTime = (Get-Date).AddDays(-30)
} | Group-Object Id |
Select-Object Count, Name, @{Name='SampleMessage';Expression={$_.Group[0].Message}} |
Sort-Object Count -Descending |
Export-Csv -Path "C:\Reports\ErrorSummary.csv" -NoTypeInformation -Encoding UTF8
# 時間帯別に集計
Get-WinEvent -FilterHashtable @{
LogName = 'System'
Level = 2
StartTime = (Get-Date).AddDays(-7)
} | Group-Object {$_.TimeCreated.ToString("yyyy-MM-dd HH")} |
Select-Object @{Name='Hour';Expression={$_.Name}}, Count |
Sort-Object Hour |
Export-Csv -Path "C:\Reports\ErrorsByHour.csv" -NoTypeInformation -Encoding UTF8
よくあるエラーと対処法
PowerShellでイベントログを操作する際に遭遇しやすいエラーと解決方法をまとめました。
エラー1: アクセス拒否
エラーメッセージ:
Get-WinEvent : アクセスが拒否されました
原因:
セキュリティログなど、管理者権限が必要なログにアクセスしようとした。
対処法:
PowerShellを「管理者として実行」で起動してください。リモートサーバーの場合は、適切な権限を持つアカウントでログインする必要があります。
# 権限確認
$CurrentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
$Principal = New-Object Security.Principal.WindowsPrincipal($CurrentUser)
$IsAdmin = $Principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-not $IsAdmin) {
Write-Warning "管理者権限で実行してください"
}
エラー2: ログ名が見つからない
エラーメッセージ:
Get-WinEvent : 指定されたログ名が存在しません
原因:
存在しないログ名を指定した、またはログが無効化されている。
対処法:
利用可能なログ名を確認します。
# 利用可能なログ一覧を表示
Get-WinEvent -ListLog * |
Select-Object LogName, RecordCount, IsEnabled |
Where-Object {$_.RecordCount -gt 0} |
Sort-Object RecordCount -Descending
# 特定のキーワードでログを検索
Get-WinEvent -ListLog * | Where-Object {$_.LogName -like "*application*"}
エラー3: リモートサーバーへの接続失敗
エラーメッセージ:
Get-WinEvent : RPC サーバーを利用できません
原因:
ファイアウォールでRPCがブロックされている、またはWinRMサービスが停止している。
対処法:
- WinRMサービスが起動しているか確認
- ファイアウォールでRPC(TCP 135)とダイナミックポートが許可されているか確認
- 以下のコマンドでWinRMを有効化
# リモートサーバー上で実行(管理者権限必要)
Enable-PSRemoting -Force
# サービス状態を確認
Get-Service WinRM
# ファイアウォールルールを確認
Get-NetFirewallRule -DisplayName "*Remote Event Log*" | Select-Object DisplayName, Enabled
# 接続テスト
Test-WSMan -ComputerName Server01
エラー4: メモリ不足エラー
エラーメッセージ:
Get-WinEvent : メモリが不足しています
原因:
大量のログを一度に取得しようとした。
対処法:
MaxEventsパラメータで件数を制限するか、FilterHashtableで期間を絞り込みます。
# 件数を制限して取得
Get-WinEvent -LogName System -MaxEvents 1000
# 期間を絞り込む
Get-WinEvent -FilterHashtable @{
LogName = 'System'
StartTime = (Get-Date).AddHours(-6)
}
# ページング処理で少しずつ取得
$MaxEvents = 1000
$Skip = 0
do {
$Events = Get-WinEvent -LogName System -MaxEvents $MaxEvents -Oldest |
Select-Object -Skip $Skip -First 1000
$Events | Export-Csv -Path "C:\Logs\System_$Skip.csv" -Append
$Skip += 1000
} while ($Events.Count -gt 0)
エラー5: FilterHashtableの構文エラー
エラーメッセージ:
Get-WinEvent : パラメーター 'FilterHashtable' にバインドできません
原因:
FilterHashtableの構文が正しくない、またはサポートされていないキーを使用している。
対処法:
ハッシュテーブルの構文を確認し、正しいキーを使用します。
# 正しい構文
$Filter = @{
LogName = 'System'
Level = 2
StartTime = (Get-Date).AddDays(-1)
}
Get-WinEvent -FilterHashtable $Filter
# 間違った構文(カンマ区切りはNG)
# $Filter = @{LogName='System', Level=2} # これはエラー
# 正しいキー名を確認
# 使用可能: LogName, ProviderName, Path, Keywords, ID, Level, StartTime, EndTime, UserID, Data
まとめ
PowerShellのGet-WinEventコマンドを使ったイベントログの収集・分析は、Windows Server運用において欠かせない技術です。本記事で紹介した以下のポイントを押さえることで、日々のトラブルシューティングが格段に効率化されます。
- Get-WinEventとFilterHashtableを使った高速なログ取得
- 複数サーバーからの一括収集で運用効率の向上
- 実践的なフィルタリングパターンで必要な情報を素早く抽出
- CSV/HTMLエクスポートによる可視化と共有
- よくあるエラーへの対処法の理解
Get-WinEventはWindows Server 2008以降で利用可能ですが、FilterHashtableの全機能を活用するには、Windows Server 2012以降の環境を推奨します。これらの技術を組み合わせることで、障害発生時の迅速な原因究明や、定期的なシステム監査を効率的に実施できます。ぜひ実務環境で活用してください。

コメント