EventLog.EntryWritten イベントが同じエントリに対して複数回発生することがある

こんにちは、Platform SDK (Windows SDK) サポートチームです。

今回は、.NET Framework の EventLog.EntryWritten イベントの不具合について報告します。

 

現象

EventLog.EntryWritten イベントはローカル コンピューター上のイベント ログにエントリが書き込まれた時に発生します。
ユーザーはこのイベントを利用してイベント ログの書き込みを監視することができますが、稀に通知済みのエントリに対して再度イベントが発生することがあります。

 

原因

EntryWritten イベント処理の内部において、どのイベントまで通知済み (登録されたハンドラーの呼び出し済み) かどうかを管理している値 (lastSeenCount) があります。
イベント ログにエントリが書き込まれる度にハンドラーが呼び出されるため、lastSeenCount は通常単調に増加します。
また .NET Framework では最も古いイベント ログのエントリ番号を表す OldestEntryNumber と、イベント ログに含まれるエントリ数に相当する EntryCount と呼ばれる値も管理しています。
本来これらは OldestEntryNumber <= lastSeenCount かつ lastSeenCount <= OldestEntryNumber + EntryCount の条件を満たしている必要があります。
しかしながら、ある稀なタイミングで上書きなどによりエントリの削除が実行された場合、この条件を満たさない状態になります。
この時 .NET Framework は lastSeenCount に OldestEntryNumber をセットするため、通知済みのイベント エントリに対するハンドラーの呼び出しが再度発生します。

 

回避策

本事象が発生しない EventLogWatcher クラスの EventRecordWritten イベントを利用してください。
EventLogWatcher クラスが利用できない場合は、EntryWritten に登録したイベント ハンドラーが呼び出された時に、処理済みのイベントかどうかを判断するロジックを実装します。

EventLogWatcher クラス
https://msdn.microsoft.com/ja-jp/library/system.diagnostics.eventing.reader.eventlogwatcher(v=vs.110).aspx

サンプルコード (How to: Subscribe to Events in an Event Log)
https://msdn.microsoft.com/en-us/library/bb399428(v=vs.90).aspx