[C#] EventLogクラスを使ってBugCheckCodeを取得する

**ブルースクリーン(BSOD)** 発生時のエラーコードのことを[**BugCheckCode**]((https://docs.microsoft.com/ja-jp/windows-hardware/drivers/debugger/bug-check-code-reference2))とよび、`C:\Windows\MEMORY.DMP`に出力されたダンプファイルを[WinDbg](https://docs.microsoft.com/ja-jp/windows-hardware/drivers/debugger/debugger-download-tools)で解析したり、イベントビューアーでBugCheckCodeを確認するのですが、仕事で既存のアプリにBugCheckCodeを解析・取得する機能を追加することになり、今回C#の[EventLogクラス](https://docs.microsoft.com/ja-jp/dotnet/api/system.diagnostics.eventlog?view=netframework-4.7)を使ってBugCheckCodeを取得しました。

**※.Net Framework 4.7 を採用しています。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438389/54c601f9-30b9-2f7e-b166-0c23b4358b83.png)

#### ソースコードサンプル
```csharp
            System.Diagnostics.EventLog[] logs =
                System.Diagnostics.EventLog.GetEventLogs();
            
            foreach (System.Diagnostics.EventLog log in logs)
            {
                // BugCheckの情報はSystemにあるので、それ以外の場合はcontinue
                if (log.Log != "System")
                {
                    continue;
                }

                //ログエントリを取得してsourceがBugCheckかチェックする
                foreach (System.Diagnostics.EventLogEntry entry in log.Entries)
                { 
                    if (entry.Source == "BugCheck")
                    {
                        Console.WriteLine(entry.TimeGenerated.ToString() + " " + entry.EventID);
                        // entry.ReplacementStringsにEventDataの値が入っている
                        // 文字列にBugCheckCodeと4つのparmsが入っているので正規表現で分解する
                        var results = Regex.Matches(entry.ReplacementStrings[0], "0x[0-9a-fA-F]+");

                        foreach(var result in results)
                        {
                            Console.Write(result);
                            Console.Write(" ");
                        }
                        Console.WriteLine();
                    }
                }
            }
```

#### 出力結果
> 2022/07/18 22:22:56 1001
0x0000007b 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000

#### 簡単な解説

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438389/617c3adf-3907-4477-492d-98066168134e.png)

```cs
            System.Diagnostics.EventLog[] logs =
                System.Diagnostics.EventLog.GetEventLogs();
            
            foreach (System.Diagnostics.EventLog log in logs)
            {
                // BugCheckの情報はSystemにあるので、それ以外の場合はcontinue
                if (log.Log != "System")
                {
                    continue;
                }
```
まず、[EventLog.GetEventLogs()](https://docs.microsoft.com/ja-jp/dotnet/api/system.diagnostics.eventlog.geteventlogs?view=netframework-4.7)でEventLogの配列を取得して、foreachの中で[EventLog.Log](https://docs.microsoft.com/ja-jp/dotnet/api/system.diagnostics.eventlog.log?view=netframework-4.7)の値を確認します。
EventLog.Logには上の図でいうと左ペインにある、`Application`、`Security`、`System`などが該当します。ちなみにイベントビューアーは[eventlog.logDisplayName](https://docs.microsoft.com/ja-jp/dotnet/api/system.diagnostics.eventlog.logdisplayname?view=netframework-4.7)というローカライズされた文字(システム、セキュリティ等)を表示してます。


```cs
 //ログエントリを取得してsourceがBugCheckかチェックする
                foreach (System.Diagnostics.EventLogEntry entry in log.Entries)
                { 
                    if (entry.Source == "BugCheck")
                    {
                        Console.WriteLine(entry.TimeGenerated.ToString() + " " + entry.EventID);
                        // entry.ReplacementStringsにEventDataの値が入っている
                        // 文字列にBugCheckCodeと4つのparmsが入っているので正規表現で分解する
                        var results = Regex.Matches(entry.ReplacementStrings[0], "0x[0-9a-fA-F]+");

                        foreach(var result in results)
                        {
                            Console.Write(result);
                            Console.Write(" ");
                        }
                        Console.WriteLine();
                    }
```

あとは[EventLog.Entries](https://docs.microsoft.com/ja-jp/dotnet/api/system.diagnostics.eventlog.entries?view=netframework-4.7)でログの内容を確認して、[EventLogEntry.Source](https://docs.microsoft.com/ja-jp/dotnet/api/system.diagnostics.eventlogentry.source?view=netframework-4.7)が`BugCheck`か判定するだけです。
BugCheckCodeと4つのパラメータは`entry.ReplacementStrings`の0番目に入っているので、今回は正規表現で後から取り出しやすいようにresults変数に代入しています。