かつて山市良と呼ばれたおじさんのブログ
セイテクエンジニアのブログ かつて山市良と呼ばれたおじさんのブログ vol.209 イベントログを使いこなせ(その1)|セイテク・シス管道場(Web)
2026年06月11日配信
執筆者:山内 和朗
「セイテク・シス管道場(Web)」では、Windows Serverの要素技術やシステム管理の基本的な部分に焦点を当ててきました。シリーズ最終回に向けてまだ説明していない主要な管理技術や管理ツールを取り上げていきます。今回は、システムの動作状態や障害の発生や予兆の発見、システム監査などに役立つイベントログとそれを参照するためのイベントビューアーです。
Windowsのイベントログは、次に示すようなシステムで発生したさまざまな動作やイベントを記録する仕組みです。これにより、システムの動作確認、障害解析、セキュリティ監査などに役立ちます。
ユーザーのログインやログオフ
システムの起動や停止
アプリケーションの動作履歴やエラー
セキュリティ関連のイベント(認証エラーやロックアウトなど)
古いバージョンのWindowsには、「アプリケーション(Application)」「システム(System)」「セキュリティ(Security)」の3つのログしかありませんでした。Windows Vista以降、イベントログがETW(Event Tracing for Windows)ベースのものに再設計され、従来の3つの標準的なWindowsログに「Setup」(インストール、更新関連)と「Forwarded Events」(他のPCからの転送イベント)が加わり、さらに「アプリケーションとサービスログ」が新設され、多くのアプリケーションが独自のログファイルにイベントを記録できるようになりました。
ログの数や構造が爆発的に増加したことで、イベントログを参照できる「イベントビューアー」(eventvwr.msc)は、Windows Vista以降、応答性が劣化したと思うのは私だけではないでしょう。イベントビューアーを開き、ログが読み取られ、参照できるようになるまで待たされると、特に急いでいるときにイライラします。
参考:
イベント ログ (イベント ログ)|Windowsアプリ開発(Microsoft Learn)
Windows標準のWEVTUTILコマンドやPowerShellのGet-WinEventコマンドレットを使用すれば、特定のログファイルの膨大なイベントから目的のイベントをすばやく検索することができます。その速さは、イベントビューアーの検索やフィルター機能と比べても、圧倒的です。
wevtutil|Windows Server(Microsoft Learn)
Get-WinEvent|Windows Server(Microsoft Learn)
アプリケーションとサービスログを含む、システムで利用可能なすべてのログ名を参照するには、次のコマンドラインを実行します。
コマンドプロンプト(cmd.exe):
| WEVTUTIL el |
PowerShell(powrshell.exe、pwsh.exe):
| Get-WinEvent -ListLog * |

画面1 Get-WinEvent -ListLog * | Where-Object {$_.RecordCount -gt 0}を実行すると、1つでもイベントが記録されているログ名を確認できる
複雑なフィルター条件を指定するには、XPATHを使用します。例えば、システム(System)ログに過去12時間(43200000ミリ秒)に記録された重大(Critical、1)またはエラー(Error、2)レベルのイベントを一覧表示するには、次のコマンドラインを実行します(画面2)。
コマンドプロンプト(cmd.exe):
| WEVTUTIL qe System /rd:true /f:text /q:"*[System[(Level=1 or Level=2) and TimeCreated[timediff(@SystemTime) <= 43200000]]]" |
PowerShell(powrshell.exe、pwsh.exe):
| Get-WinEvent -LogName System -FilterXPath "*[System[(Level=1 or Level=2) and TimeCreated[timediff(@SystemTime) <= 43200000]]]" |

画面2 ステム(System)ログに過去12時間(43200000ミリ秒)に記録された重大(1)またはエラー(2)イベントを列挙
XPATHの記述が難しそうと思うかもしれませんが、このXPATHはイベントビューアーの「現在のログをフィルター」ウィンドウを利用して簡単に作成できます。「フィルター」タブで条件を設定したら、「XML」タブに切り替え、<Select Path="System">と</Select>の間の文字列をコピーします。この文字列をXPATHとしてWEVTUTILやGet-WinEventに指定することができます。ただし、コピーしたテキストに「<=」や「>=」が含まれている場合は、それらを「<=」や「>=」に修正する必要があります(画面3)。

画面3 XPATHは「フィルター」タブでフィルターで条件を作成し、「XML」タブからコピーして、必要に応じてHTMLエンティティをデコードすれば完成する
|
参考: Get-WinEventでは、-FilterHashTableや-FilterXmlでフィルター条件を設定することもできます。-FilterXmlのXMLクエリは、イベントビューアーのフィルターの「XML」タブ(後述)の内容(緑色の文字の部分)をそのままコピーして使用できます。「<=」や「>=」を修正する必要はありません。
|
Get-WinEventは、PowerShellの強力なスクリプティング機能を利用できるという利点があります。次のコードは、vol.200で紹介したもので、最後のコールドブートまたは再起動($lastcodeboot)またはスリープ/休止状態からの再開した時間($lastresume)を取得し、最後の起動日時($lastboot)と現在の時刻との差を「日:時間:分:秒」の形式で表示します(画面4)。
| $events = Get-WinEvent -LogName System -FilterXPath "*[System[Provider[@Name='Microsoft-Windows-Kernel-General' or @Name='Microsoft-Windows-Kernel-Power'] and (EventID=12 or EventID=107 or EventID=1)]]" | Sort-Object TimeCreated $lastresume = $null for ($i = 0; $i -lt $events.Count; $i++) { if ($events[$i].Id -eq 107) { for ($j = $i+1; $j -lt $events.Count; $j++) { if ($events[$j].Id -eq 1) { $lastresume = $events[$j].TimeCreated break }}}} $lastcoldboot = $null $lastcoldboot = ($events | Where-Object {$_.Id -eq 12} | Select-Object -Last 1).TimeCreated $lastboot = @($lastresume, $lastcoldboot) | Where-Object { $_ } | Sort-Object -Descending | Select-Object -First 1 (((Get-Date) - $lastboot)).ToString("d\:hh\:mm\:ss") |
最後のコールドブートや再起動の日時は、Kernel-Generalの最新のイベントID 12(オペレーティングシステムはシステム時刻 XXX に起動しました)が記録された日時で識別できます。スリープ/休止状態からの再開はKernel-PowerのイベントID 107(システムがスリープ状態から再開されました)で判断できますが、その日時はスリープ/休止状態に入った時の古い日時を示しています。そのため、イベントID 107の直後に記録されるKernel-Generalのイベント ID 1(システム時刻の変更)の日時を再開時間として判断しています。最後に、最後のコールドブートの日時($lastcoldboot)と最後の再開日時($lastresume)でより新しい日時と、現在の日時の差を計算しています。

画面4 PCの電源をオンにしてからの経過時間をイベントから計算する。再開した日時はイベントID 107の直後のイベントID 1の日時
WEVUTILのほうは、PowerShellを利用できないWindows回復環境(WinRE)コマンドプロンプトでも実行できるという利点があります。システムが正常に起動しなかった場合、WinREのコマンドプロンプトを開いて、オフラインのログファイルを参照することができます(画面5)。ログファイルは、OSドライブのマウント先の「¥Windows¥System32¥winevt¥Logs¥」(System.evtx、Application.evtx、Security.evtxなど)に存在します。
WinREのコマンドプロンプト(cmd.exe):
| WEVTUTIL qe /lf ドライブ文字:\Windows\System32\winevt\Logs\System.evtx /rd:true /f:text /q:"*[System[(Level=1 or Level=2) and TimeCreated[timediff(@SystemTime) <= 43200000]]]" |

画面5 WEVTUTILは、WinREのコマンドプロンプトでも使用でき、オフラインシステムのログファイルを検索できる
UNIXやLinuxシステムでは、ログをリアルタイムに監視するために「tail -f /var/log/messages」を実行したりします。このコマンドはログファイル(/var/log/messages)の末尾に新しいログエントリが追加されたらリアルタイムに逐一表示してくれるものです。次のPowerShellのコードは、同じようなことをWindowsのイベントログに対して実現しようと考えて作成したものです。対象は特定のログではなく、Get-WinEvent -ListLog *で取得した存在するすべてのログが対象です。すべてのログを対象に、2秒ごとに新しいログが記録されていればそれを表示します(画面6)。

画面6 tail -f 風にイベントログをリアルタイム監視
| $logs = (Get-WinEvent -ListLog * | Where-Object {$_.IsEnabled}).LogName 2>$null $last = Get-Date while ($true) { $events = Get-WinEvent -FilterHashtable @{ LogName = $logs StartTime = $last } -ErrorAction SilentlyContinue if ($events) { $events = $events | Sort-Object TimeCreated $events | Select TimeCreated, LogName, Id, LevelDisplayName, Message $last = $events[-1].TimeCreated } Start-Sleep -Seconds 2 } |
セイテク・シス管道場(Web) (1) |・・・|(10)|(11)|(12)|(13)|(14)|(15)|(16)|(17)