セージ の メモ書き

メモこそ命の恩人だ

C# - OSイベントログの取得

wevtutil コマンド

docs.microsoft.com

  • Windows のコマンドで取得する。
  • 詳細な検索条件は指定できない。

こんな感じ。

// wevtutil:イベントログ管理用のコマンド
// eplオプション:evtx形式で出力可能(export-log)
// https://docs.microsoft.com/ja-jp/windows-server/administration/windows-commands/wevtutil

// wevtutil により高速に出力可能
// https://qiita.com/sta/items/957d78a8e884f23cb8be


var name = "system";
var path = $@"{Environment.CurrentDirectory}\{name}.evtx";
var processStartInfo = new ProcessStartInfo()
{
    // コマンド指定
    FileName = "cmd.exe",
    Arguments = $"/c wevtutil epl {name} {path}",
    // ウィンドウ表示:無効
    CreateNoWindow = true,
    UseShellExecute = false,
    // ファイル出力:有効
    RedirectStandardInput = false,
    RedirectStandardOutput = true,
};
Process.Start(processStartInfo);


EventLogQuery クラス

docs.microsoft.com

  • OSのイベントログを取得できる。
  • System.Diagnostics.EventLogクラスは使用しないこと。
    • 旧OS用のため(非推奨)
    • EventLogQuery クラスの方が高速のため
    • EventLogQuery クラスの方が検索条件が充実してるため

準備:クエリ定義

  • [コントロールパネル -> 管理ツール -> イベントビューア―] を起動する。
  • 左側のツリーより、対象のWidowsログを選択する。
  • 右側より、[現在のログフィルター]を選択する。
  • [フィルター]タブで任意の条件を指定する。
  • [XML]タブより、クエリを確認する。クエリをコピーしとく。

条件未指定だと、こんな感じ。

<QueryList>
  <Query Id="0" Path="System">
    <Select Path="System">*</Select>
  </Query>
</QueryList>

24時間前の条件を付与すると、こんな感じ。

<QueryList>
  <Query Id="0" Path="System">
    <Select Path="System">*[System[TimeCreated[timediff(@SystemTime) &lt;= 86400000]]]</Select>
  </Query>
</QueryList>

実装方法

  • クエリを加工する。
    • 改行を抜く。
    • 「"」にエスケープ処理を行う。
<QueryList><Query Id="0" Path="System"><Select Path="System">*</Select></Query></QueryList>
↓
@"<QueryList><Query Id=""0"" Path=""System""><Select Path=""System"">*</Select></Query></QueryList>"
<QueryList><Query Id="0" Path="System"><Select Path="System">*[System[TimeCreated[timediff(@SystemTime) &lt;= 86400000]]]</Select></Query></QueryList>
↓
@"<QueryList><Query Id=""0"" Path=""System""><Select Path=""System"">*[System[TimeCreated[timediff(@SystemTime) &lt;= 86400000]]]</Select></Query></QueryList>"

こんな感じで、イベントビューアーに近い情報を取得できる。

private IEnumerable<string> GetSystemLog()
{
    var eventLogQuery = new EventLogQuery(
        path: "System",
        pathType: PathType.LogName,
        query: @"<QueryList><Query Id=""0"" Path=""System""><Select Path=""System"">*[System[TimeCreated[timediff(@SystemTime) &lt;= 86400000]]]</Select></Query></QueryList>")
    {
        ReverseDirection = true,    // 新しいログから取得
    };

    var eventLogReader = new EventLogReader(eventLogQuery);
    var delimiter = '\t';
    while (true)
    {
        var eventRecord = eventLogReader.ReadEvent();
        if (eventRecord == null) break;
        yield return
            $"レベル:{eventRecord.Level}{delimiter}" +
            $"時刻:{eventRecord.TimeCreated}{delimiter}" +
            $"ソース:{eventRecord.ProviderName}{delimiter}" +
            $"イベントID:{eventRecord.Id}";
    }
}



以上