イベント ログには、標準ログとしてアプリケーションやサービスが出力するアプリケーション ログ、OS のコアやコンポーネントやデバイス ドライバが出力したり、サービスの稼働状況が出力されるシステム ログ、オブジェクト (リソース) 使用イベントやログオンの記録が出力されるセキュリティ ログがあります。そのほかにも環境によってはアプリケーションが独自に作成するカスタム ログ (DNS サーバー ログ、ディレクトリ サービス ログなど)が存在します。
PowerShell に標準で付属している Get-EventLog コマンドレットを使うと、WSH などと比べて非常に容易にこれらのイベント ログにアクセスすることが可能です。
| Get-EventLog コマンドレット | |
| カスタム フィルタの作成 | |
| まとめ |
システムに記録されているイベント ログの種類をリストアップするには Get-EventLog コマンドレットに –list パラメータを付加して実行します。実行例を図 1 に表示します。

図 1 イベント ログの一覧表示
Max(K) はイベント ログの最大ログ サイズ (キロバイト単位)、Retain はイベント ログ内のエントリを保持する日数、イベント ログが最大ファイル サイズに達した場合に既存のエントリを破棄する・上書きするなどの設定、Entries はエントリの数、Name はイベント ログの表示名です。
実際に各イベント ログのログを取得するには Get-EventLog コマンドレットにログの名前を –logName パラメータで指定するのですが、指定する名前は表示名とは異なります。そこで、-list パラメータに –asString パラメータを追加して実行するとログの名前の一覧が取得できます。実行例を図 2 に示します。

図 2 イベント ログ名の一覧表示
ここに表示されたイベント ログの名前を Get-EventLog コマンドレットの –logName パラメータに指定すると、実際のイベント ログのエントリが一覧表示されます。なお、-logName パラメータはパラメータ名を省略することができます。パラメータに半角スペースが含まれる場合 (Directory Service など) は、"" (ダブル クォーテーション) あるいは '' (シングル クォーテーション) で括ります。
実際のイベント ログ エントリは数千から数万に達することも多く、すべて表示させるのは現実的ではありません。そこで、-newest パラメータを併用し、最新の数個のエントリを取得するのがよいでしょう。次の例は、アプリケーション イベント ログの最新 15 個のエントリを取得するものです。

図 3 アプリケーション イベント ログのエントリ表示
ここで Index はエントリのインデックス、Time はイベントが生成された時刻 (日 月 時:分)、Type はイベントの種類、Source はイベントを発生させたアプリケーションの名前、EventID はイベント エントリのアプリケーション固有のイベント識別子、Message はイベント エントリに関連付けられているメッセージです。
ここで表示された Index が 9735 のイベントの詳細を表示させたい場合は、次のようにパイプを通じて Where-Object コマンドレットでフィルタ スクリプトを実行し、その結果フィルタされたエントリのプロパティ一覧を Format-List コマンドレットで表示すると良いでしょう。実行例を図 4 に示します。

図 4 イベント ログ エントリの詳細
これで、Message などが省略されずに全部を読むことができます。
同様に、Where-Object コマンドレットに与えるフィルタ スクリプトを{[DateTime]"2006/12/1" -lt $_.TimeGenerated -and $_.TimeGenerated -lt [DateTime]"2006/12/5"} } のようにすると、2006/12/1 から 2006/12/5 までに生成されたイベント ログを抽出できます。
なお、古いほうから数個のエントリを取り出すには、「Get-LogEvent | Select-Object -last 15」のように、Get-EventLog コマンドレットの出力を Select-Object コマンドレットにパイプで渡し、-last パラメータに取得したい数を指定します。
先ほどの例では Where-Object コマンドレットを用い、フィルタ スクリプトのスクリプト ブロックを指定しましたが、毎回フィルタを打ち込むのは面倒です。そこで、ここでは filter を用いて、一度記述することで何回も呼び出し可能なカスタム フィルタをスクリプト ファイルに作成してみましょう。
PowerShell のデフォルトのスクリプト実行ポリシーは "Restricted" であり、スクリプトの実行が許可されていないので、Set-ExecutionPolicy コマンドレットを用い実行ポリシーを、"RemoteSigned" (リモートのスクリプトには署名が必要だが、ローカルのスクリプトはすべて実行可) などに変更してください。
filter は function と並ぶ、PowerShell の「関数」の一つであり、一連の手続きを繰り返して呼び出すためのコード ブロックです。パイプラインにオブジェクトが入力されるたびに実行されます。主に、パイプラインに渡されたオブジェクトをフィルタしたり加工したりする際に用いられます。
まずは例として、24 時間以内に生成したイベント ログ エントリを抽出するフィルタを作成します。
カレント フォルダに eventlog.ps1 というテキスト ファイルを作成し、以下のように記述します。
filter Last24Hours
{
if($_.TimeGenerated -gt (Get-Date).AddHours(-24))
{
return $_
}
}
このスクリプトにおいては、filter を用い、Last24Hours という名前のフィルタを作成しています。filter 中では $_ という変数 (PowerShell においては $ が変数名の頭文字となります) にパイプで渡されたオブジェクト (ここでは EventLogEntry オブジェクト) が格納されています。そこで、if ステートメントをもちい、$_ の TimeGenerated プロパティ (イベントの生成時刻) が現在時刻の 24 時間前 (Get-Date コマンドレットの戻り値である DateTime オブジェクトの AddHours メソッドに引数 -24 を与えて取得) より先の時刻かどうかを判定し (-gt 演算子は Greater Than の略)、そうであった場合は、「return $_」としてそのまま入力オブジェクトを出力しています (return は省略可)。他の場合、すなわち 24 時間以内ではない場合は値を返しません。
実際にこのフィルタを使ってみましょう。「. .\eventlog.ps1」を実行し、このスクリプトを現在のスコープに読み込ませます。(プロファイル C:\Documents and Settings\<ユーザー名>\My Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 に filter を直接記述しておくと、使用のたび毎回呼び出す必要がありません)
そして実際にパイプを介して呼び出してみたのが次の例です。

図 5 24 時間以内に生成されたエントリの表示
このように、24 時間以内に生成されたエントリだけを抽出することができます。これでも量が多い場合は Select-Object コマンドレットを併用して適宜表示範囲を絞るか、あるいはもっと絞り込みをかけたフィルタを用意するのがいいでしょう。例として 24 時間以内に生成されたエントリのうち、Source が "MSSQL$SQLEXPRESS" であるものを出力するフィルタを作ってみましょう。次の記述を先ほどの eventlog.ps1 に追加してください。
filter MSSQLLast24Hours
{
if($_.TimeGenerated -gt (Get-Date).AddHours(-24) -and `
$_.Source -eq "MSSQL`$SQLEXPRESS")
{
return $_
}
}
ここでは –and 演算子を用いて、複数の条件を記述しています。1 つ目の条件は先ほどと同じですが、2 つ目は入力オブジェクトの Source プロパティが "MSSQL$SQLEXPRESS" と等しいという条件です (-eq 演算子は EQual の略)。なお、$ という文字は変数の頭文字を表す特別な文字なので、` (アクサングラーブ) でエスケープする必要があります。-and 演算子の後に記述されている`は、継続文字で、1 行の記述を 2 行以上に分けるときに使います。ここでは 1 つ目と 2 つ目の条件がどちらも成立するときに、このフィルタは入力オブジェクトをそのまま出力します。このフィルタを使った実行例は次のようになります。

図 6 特定ソースのエントリ表示
このようにソースごとにフィルタを作成するのも一つの方法論ですが、ある程度フレキシブルに使用できるように、ソース名と過去何時間分のデータを取得するかを使用するたびに入力するようにすることもできます。それには filter の param キーワードを用います。次のコードをご覧ください。
filter LastNHours
{
param([string]$source, [int]$hour=24)
if($_.TimeGenerated -gt (Get-Date).AddHours(-$hour) -and `
($_.Source -eq $source -or $source -eq ""))
{
return $_
}
}
このスクリプトにおいては、ソース名と過去何時間分のデータを取得するかをパラメータで指定できるようになっています。param キーワードは () 内に , で区切ることで複数のパラメータを持たせることができます。[] 内の文字列は型 (パラメータとして与えるオブジェクトの種類) を示しています。ここでは string (文字列) と int (整数) のパラメータを受けるようにしています。また、= の後にはデフォルト値 (パラメータに何も与えなかった場合に適用される値) を指定可能です。これらのパラメータはコマンドレットのパラメータと同様の呼び出し方ができます。「LastNHours -source MSSQL`$SQLEXPRESS -hour 5」のように省略せずに呼び出すことも、「LastNHours MSSQL`$SQLEXPRESS 5」のようにパラメータ名を省略することも可能です。「LastNHours MSSQL`$SQLEXPRESS」のように、-hour パラメータを省略することもできます。
if ステートメントでは、$hour 時間前よりも最近であり、かつ、$_.Source と $source (パラメータで指定される文字列) が等しいもしくは空文字列 (パラメータを指定しなかった場合) の場合を判別して、入力オブジェクトをそのまま出力します。
実際にシステム イベント ログから過去 5 時間に W32Time で発生したイベントを一覧表示してみましょう。結果はたとえばこのようになります。

図 7 ソース名と時間を指定してエントリを表示
PowerShell に含まれるコマンドレットのうち、イベント ログのような多数のオブジェクトが返されることが多いコマンドレットを使用する際は、Where-Object コマンドレットを使ってフィルタをかけることが必要となります。しかし、よく使うフィルタに関しては filter を用いてスクリプト化、あるいはプロファイルに記述することで繰り返し利用することができます。例えば Get-EventLog コマンドレットに filter を併用することで大量のイベント ログを効率よく閲覧することが可能になります。

執筆者 : 牟田口 大介
Windows Script Host を始めとする Windows Script に関するサイトを 1999 年より主催し、その掲示板で質疑応答、ディスカッション等を行っている。
また、コミュニティ「わんくま同盟 (http://www.wankuma.com/)」に加盟し、主にPowerShell に関するブログを更新中。
その他、フリーで Windows Script や PowerShell に関する Web 記事、書籍などの執筆活動を展開中。