Windowsイベントログ解析:PowerShellで特定のイベントIDを監視する方法

特定event IDのWindows log監視は短い一行でも扱えますが、入力の種類や版を確認しないまま本番へ使うと誤判定を招きます。この記事の結論は「過去logはGet-WinEventのFilterHashtableで期間・log・IDを絞り、継続監視は定期queryまたはWindows Event Forwardingなど管理基盤へ渡します。Get-EventLog全件をWhere-Objectで後filterする旧例は避けます。」。event IDだけでなくLogNameとProviderNameを固定し、Security logは必要権限と取扱規程を守る場合を対象に、確認結果から次の行動を選べる形で解説します。

目次

channel・provider・ID・時間窓を固定する

event queryのchannel・provider・IDは実値へ固定し、曖昧なwildcardをcursor処理へ残しません。Get-WinEventがshell builtin、cmdlet、外部programのどれかも確認し、別実装のoptionを混在させません。

  • Get-WinEvent -ListLogでlog名とenabled状態を確認する
  • 対象IDのProviderName、level、意味を公式event資料で確認する
  • baseline件数と監視window、重複除外用RecordIdを決める
  • Security logの閲覧権限と保存先ACLを確認する

FilterHashtableで取得前に絞り込む

直近一時間をserver-side filter

$start=(Get-Date).AddHours(-1)
Get-WinEvent -FilterHashtable @{LogName='System';Id=7036;StartTime=$start} -MaxEvents 200 |
  Select-Object TimeCreated,RecordId,Id,ProviderName,LevelDisplayName,Message

ID 7036はSystem logのService Control Manager例です。IDだけを別providerへ一般化しません。

providerも固定

Get-WinEvent -FilterHashtable @{LogName='System';ProviderName='Service Control Manager';Id=7036;StartTime=(Get-Date).AddMinutes(-15)}

ProviderNameを組にすると同番号別eventの混入を防ぎます。

最後に処理したRecordIdを記録

$events=Get-WinEvent -FilterHashtable @{LogName='System';Id=7036} -MaxEvents 20
$events | Sort-Object RecordId | Select-Object TimeCreated,RecordId,Message

定期pollでは前回最大RecordIdと時刻をcheckpointにします。log clearやwrapで連続性が失われる条件も監視します。

event XMLのdata名を確認

$e=Get-WinEvent -FilterHashtable @{LogName='System';Id=7036} -MaxEvents 1
[xml]$xml=$e.ToXml()
$xml.Event.EventData.Data | Select-Object Name,'#text'

message文字列の位置splitより、XMLのnamed dataを使えるか確認します。schemaはproviderごとに異なります。

少量をCLIXMLへ保存

$events | Export-Clixml -LiteralPath '.\event-7036-sample.xml'

Messageにはsystem情報が含まれます。限定ACL、新規file、保持期限を設定します。

RecordId cursorはchannelごとに保持する

  • Get-EventLog全件後filter
  • event IDだけで意味を断定する
  • poll境界で重複を数える
  • Message文言を固定splitする
  • 調査中にlogをclearする

event XMLから名前付きdataを読む

監視はevent発生と同時に原因確定するものではありません。同じIDが正常遷移でも出るか、短時間に連続したか、関連eventが前後にあるかを見ます。TimeCreated、RecordId、ProviderNameを組にし、poll windowの境界で重複または欠損しない設計にします。Event Viewer表示languageに依存するMessage解析は避けます。

CLIXMLでobject構造を保存する

log取得は読み取りですが、Security logにはaccount、host、network情報が含まれます。広い共有先や平文mailへ出さず、collection serviceの権限と保持policyに従います。logをclear、disable、size縮小して監視を軽くしません。監視scriptにcredentialを埋め込まず、失敗時はcheckpointを勝手に進めず再取得範囲をreviewします。

log clear・wrap・取得gapを検出する

Event Viewerの同一RecordIdを照合し、既知eventをtest環境で一件発生させて検知遅延と重複を確認します。query失敗、0件、access denied、log wrapを別statusへ記録します。定期監視は終了code、最終成功時刻、checkpointを監視対象に含めます。

時刻順・件数・最大RecordIdを検収する

FilterHashtableでlog/provider/ID/期間を絞り、RecordId、TimeCreated、Level、event XMLのnamed Dataを保持します。Messageは表示用とし、増分cursorはhost・logごとのRecordIdで管理して重複と取りこぼしを検出します。

System 7036を上限付きで増分取得する

$e=@(Get-WinEvent -FilterHashtable @{LogName='System';ProviderName='Service Control Manager';Id=7036;StartTime=(Get-Date).AddHours(-1)} -MaxEvents 200 -ErrorAction Stop)
$e | Sort-Object RecordId | Select-Object TimeCreated,RecordId,Id,ProviderName

cursor進行とchannel障害をRecordIdで追う

  • 増分eventあり:filter条件に一致するeventをRecordId順に取得し、XML Data名から必要fieldを読める
  • 新規eventなし:0件はcursorを勝手に進めず、query期間と最終RecordIdを保持する
  • channel・query error:log clearでRecordIdが戻る、channel unavailable、権限不足、malformed queryは別alertにする

MaxEventsだけで期間を省略すると高頻度時に調査範囲が変わります。Message regexはlanguage差で壊れるため、ProviderName/Id/XML fieldを使い、CLIXMLを無制限に保存しません。

RecordId gapと同時刻eventを試す

$one=Get-WinEvent -FilterHashtable @{LogName='System';Id=7036} -MaxEvents 1
[xml]$xml=$one.ToXml(); $xml.Event.EventData.Data | Select-Object Name,'#text'

0件、同時刻複数event、log clear、provider名違い、access deniedをtestします。host/log、query、最小/最大RecordId、件数、XML schema、取得時間を保存します。

RecordIdは全log共通の連番ではありません。channel名と最後のRecordIdを一組で保存し、log clearやretentionによる巻き戻りを検出した場合は増分処理を止めて再baselineします。

公式情報・参考資料

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次