Get-WinEventコマンドレットにおいて、フィルターで日時を指定してイベントログを絞り込む方法。

日時で絞り込む方法はGet-WinEventコマンドのヘルプに載っています。なのでわざわざ取り上げるような話ではないと思っていましたが、話題として全く取り上げられていない≒あまり知られていないようなので、少し触れてみることにします。ところで一言付け加えておくと、私はITを専門・職業とする技術者ではなく単に個人で使い込んでいるだけなので、このサイトの情報をシステム開発・管理などの業務に利用しようと考えている方は注意して下さい。

Get-WinEventコマンドで日時フィルターを指定する方法は主に3通りに分けられます。

  1. コマンドで返されるオブジェクトの型がEventLogRecordクラスなので、そのTimeCreatedプロパティ(DateTime型)と比較する方法。
  2. ハッシュテーブルのクエリでStartTimeキー、EndTimeキーを指定する。
  3. XPathのフィルタークエリでTimeCreated要素の比較やtimediff関数(非標準)を利用する。

1の方法の場合はまずGet-WinEventコマンドを実行してから、Where-ObjectコマンドでTimeCreatedプロパティの条件を指定してパイプで繋ぐことになります。この方法は、Get-WinEventコマンドで取得するイベントログが数万件もあると実行に時間が掛かってしまいます。2の方法が効率がよく、わかりやすいスクリプトになるのでお勧めです。ただ、複雑な条件を指定できないという点ではXPathに劣ります。3の方法では複雑な条件を指定できる代わりにやや読みにくい(難解な)スクリプトになります。

○例1 過去3日間のSystemログのイベントログを取得する

方法はGet-WinEventコマンドのヘルプの例14とほぼ同じです。行頭のPSは省いてください。

# 方法1 (注:場合によっては処理が終わるまでにかなり時間がかかります。)
PS $startdate = (get-date) - (new-timespan -day 3)
PS get-winevent -logname "System" | where {$_.timecreated -ge $startdate}

# 方法2
PS $startdate = (get-date) - (new-timespan -day 3)
PS get-winevent -FilterHashTable @{LogName='System'; StartTime=$startdate}

# 方法3
PS get-winevent -LogName "System" -FilterXPath "*[System[TimeCreated[timediff(@SystemTime) <= 259200000]]]"

方法2はWindows Vistaで実行すると"パラメータが間違っています。"というエラーが返ってきます。これはバグらしく、Windows 7では修正されたためちゃんと実行できます。
方法3ではtimediff関数を使っています。これはWindowsのイベントログのXPathフィルター特有の関数であり、XPathの標準仕様にはありません。timediff関数でTimeCreatedとSystemTimeの差を出して、それが259200000(ミリ秒)=3日以内、というように条件を指定しています。

○例2 2011年12月1日から同月7日までの間の全ユーザーのログオン履歴を取得する

# 方法1 (注:場合によっては処理が終わるまでにかなり時間がかかります。)
PS $timeoffset = new-object System.TimeSpan 9,0,0
PS $starttime = new-object System.DateTimeOffset 2011,12,1,0,0,0,0,$timeoffset
PS $endtime = new-object System.DateTimeOffset 2011,12,7,23,59,59,999,$timeoffset
PS get-winevent -logname "Security" | where {($_.ProviderName -eq 'Microsoft-Windows-Security-Auditing') -and ($_.id -eq 4624) -and ($_.timecreated -ge $starttime.LocalDateTime) -and ($_.timecreated -le $endtime.LocalDateTime)}

# 方法2
PS $timeoffset = new-object System.TimeSpan 9,0,0
PS $starttime = new-object System.DateTimeOffset 2011,12,1,0,0,0,0,$timeoffset
PS $endtime = new-object System.DateTimeOffset 2011,12,7,23,59,59,999,$timeoffset
PS get-winevent -FilterHashTable @{LogName='Security'; ProviderName='Microsoft-Windows-Security-Auditing'; ID=4624; StartTime=$starttime.LocalDateTime; EndTime=$endtime.LocalDateTime}

# 方法3
PS get-winevent -logname Security -filterxpath "*[System[Provider[@Name='Microsoft-Windows-Security-Auditing'] and (EventID=4624) and TimeCreated[@SystemTime>='2011-11-30T15:00:00.000Z' and @SystemTime<='2011-12-07T14:59:59.999Z']]]"

以前の記事で述べたとおり、Securityログへのアクセスには(たぶん)管理者権限が必要です。

方法1、方法2について。$timeoffsetにはこれから指定する日時とUTCとの時差を設定し、$starttime、$endtimeで日本時間で日時を設定しています。get-wineventコマンド実行時にはLocalDateTimeプロパティで現地日時に変換します。(タイムゾーンが日本に設定されている場合はそのまま。)まあ普通に使っている分にはこんな回りくどいことしなくても、初めからDateTime型で指定すればいいのですが。

方法3では日時をUTCで指定する必要があるので注意して下さい。XPathがよくわからない or 考えるのが面倒ならイベントビューアーでXPathのフィルタークエリを作成するといいでしょう。

現在のログをフィルタ - イベントビューアー
現在のログをフィルタ(XML)

FilterXPathスイッチで指定するときはSelectタグで囲まれた部分だけをコピーして持ってきます。FilterXmlスイッチで指定するときは全てをコピーします。今まで紹介してきませんでしたが、Get-WinEventコマンドのフィルターの指定方法はFilterXPath、FilterHashTableの他にFilterXMLがあります。FilterXMLでは複数のXPathを使って複雑なクエリを作成することができますが、それほど使う機会はないでしょう。


※コメント欄が表示されない場合はdisqusについてJavascriptが有効であることを確認して下さい。コメントはスパム防止フィルターによる承認制のため、投稿してもすぐに反映されない場合があります。

管理人 : Akamaki (akm)

は、PCとVTuberに夢中になっている電気技術者です。

私はレトロコンピューティングの愛好家ですが、そのようなリグはもう収集していません。

私の活動はトップページで見ることができます。読んでくれてありがとう!