Windows10 April 2018 Update適用でC#からイベントログ取得がうまくいかない

Windows10の大型アップデート「April 2018 Update」(バージョン1803)を適用すると、
C#から、うまくイベントログを拾えなくなってしまった。

イベントログ取得できない

例えば、以下のソースを実行すると、イベントログを途中まで読み込んで
勝手にループを抜けてしまう。

EventLog evlog = new EventLog("System", ".");
Debug.WriteLine("件数:" + evlog.Entries.Count);
foreach(EventLogEntry et in evlog.Entries)
{
    Debug.WriteLine(et.TimeGenerated);
}

実行結果:

件数:2433
2018/05/11 20:10:55
2018/05/11 20:11:25
2018/05/11 20:11:25
2018/05/11 20:10:55
:
2018/05/11 20:13:16
'WindowsFormsApp1.exe' (CLR v4.0.30319: WindowsFormsApp1.exe): 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.resources\v4.0_4.0.0.0_ja_b77a5c561934e089\System.resources.dll' が読み込まれました。モジュールがシンボルなしでビルドされました。
例外がスローされました: 'System.InvalidOperationException' (System.dll の中)
'WindowsFormsApp1.exe' (CLR v4.0.30319: WindowsFormsApp1.exe): 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\mscorlib.resources\v4.0_4.0.0.0_ja_b77a5c561934e089\mscorlib.resources.dll' が読み込まれました。モジュールがシンボルなしでビルドされました。
プログラム '[3968] WindowsFormsApp1.exe' はコード 0 (0x0) で終了しました。

⇒イベントログ2433件あるのに、123件しか取得できない。

 
 

今度は、途中で抜けないようforeachでなく、for文で件数分しっかり回し、
しかも、例外が出ても強制的にループを回してみる。

EventLog evlog = new EventLog("System", ".");

for (int i = 0; i < evlog.Entries.Count; i++)
{
    try
    {
        Debug.WriteLine(i.ToString("[0] ") + evlog.Entries[i].TimeGenerated);
    }
    catch (System.ArgumentException ex)
    {
        Debug.WriteLine(ex.Message);
    }
}

 

実行結果:

[0] 2018/05/11 20:10:55
[1] 2018/05/11 20:11:25
[2] 2018/05/11 20:11:25
:
[122] 2018/05/11 20:13:16
'WindowsFormsApp1.exe' (CLR v4.0.30319: WindowsFormsApp1.exe): 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.resources\v4.0_4.0.0.0_ja_b77a5c561934e089\System.resources.dll' が読み込まれました。モジュールがシンボルなしでビルドされました。
例外がスローされました: 'System.InvalidOperationException' (System.dll の中)
例外がスローされました: 'System.ArgumentException' (System.dll の中)
[123] インデックス 123 が境界を越えています。
[124] 1970/03/28 20:20:03
[125] 1970/03/28 20:20:03
[126] 1970/03/28 20:20:03
:
[2431] 1970/03/28 20:20:03
[2432] 1970/03/28 20:20:03

⇒やっぱり123個目で例外発生。
 catchして、それ以降の配列に何が入っているか表示してみると、1970/3/28と
 絶対あり得ないイベントログの日付が入っている。
 EventLogのEntriesとして配列は用意されたが、まともなデータが格納されていない。

 
 

これ、Updateによるバグだよね?
それとも仕様変更(非互換)?

回避できるのかな。。

自作ソフトの勤務時間取得ツールで、イベントログ読み込んでいるので
この仕様変更は非常に困る。

バグってことで、またWindows Updateで直らないかなぁ。

 
<追記>

ダメモトでシステムのイベントログを全削除してみた。
イベントログの削除
イベントビューアーの削除確認

けど、やっぱり駄目。
今度は、削除後に追加されたイベントも取得できない。

なので、まともに取得する方法は諦め、Windows PowerShellのGet-WinEventで取得する方法で回避。

PowerShellを使うため、先頭で以下を宣言。

using System.Management.Automation;

更に、参照で以下のdllを追加。
格納先例:
C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\3.0\System.Management.Automation.dll

で、以下のような処理。

string machineName = "localhost";
string targeEvtLog = "system";

RunspaceInvoke rInv = new RunspaceInvoke();
System.Collections.ObjectModel.Collection<PSObject> events = rInv.Invoke(@"Get-WinEvent " + targeEvtLog + " -ComputerName " + machineName + " |select-object TimeCreated,ID|sort-object TimeCreated");

foreach (var ev in events)
{
    Debug.WriteLine(
        String.Format(
            "{0} - {1}",
            ev.Properties["TimeCreated"].Value,
            ev.Properties["ID"].Value
        )
    );
}

 

出力結果:

2018/06/01 20:01:45 - 104
2018/06/01 20:01:49 - 6105
2018/06/01 20:02:07 - 6105
2018/06/01 20:02:20 - 16
2018/06/01 20:02:21 - 43
:
2018/06/02 15:27:48 - 37
2018/06/02 15:27:54 - 1
2018/06/02 15:27:54 - 35
2018/06/02 15:27:54 - 1
2018/06/02 15:29:47 - 10016
2018/06/02 15:33:58 - 10016

これで解決!

と思ったけど、machineNameを別マシンに書き換えたら失敗。
そりゃそうだ。
IDもパスワードも指定していないや。

そこも調べないと。
でも、ローカルPCだけならこれでOK。

それでも、やっぱり、こんな修正方法は嫌だな。
dllも多分配布しなきゃならないだろうし。

もうちょっと待ってればWindows updateで修正されるかなぁ。

 
 
<そして更に追記>
どうも、修正されないっぽい。これはおかしい。
バグじゃなくて仕様(非互換)なのかも。
上記<追記>の方法でも動作はするんだけど、PowerShellを使わなきゃならないので、やっぱりこの方法は避けたい。

で、調べなおしてみたら、このSystem.Diagnostics.EventLogはWindows XPなど古いOS向けの形式のようで、
新しいOSでは、System.Diagnostics.Eventing.Reader.EventLogReaderを使った方が良いらしい。

そんな訳で、この方法で勤務時間取得ツールもVer3.10で直してみました。
 
 


Tagged:

Leave a comment

メールアドレスが公開されることはありません。

CAPTCHA


*