はじめに
C#でイベントログを出力するには通常 EventLog.WriteEntry メソッドを使うのが一般的だと思うのですが、本エントリはそうではなく EventLog.WriteEvent メソッドを使ってイベントログを出力する方法を紹介します。
仕事でとあるイベントログの監視ツールに対してイベントログを出力する必要があって、「簡単だろう」と高を括っていたら意外とはまってしまったのが今回の内容です。
作業環境はこんな感じです。
- Windows 7 Ultimate
- Microsoft Visual C# 2010 Express
- Microsoft Visual C++ 2010 Express
- Microsoft Windows SDK v7.1
メッセージリソースDLLを作る
最初にイベントログに出力するメッセージを格納するメッセージリソースDLLを作成します。
メッセージリソースDLLは以下の手順で作成することができます。
- メッセージを記述したメッセージスクリプトを作成し、メッセージコンパイラ(mc.exe)でコンパイルしリソーススクリプトを作成する。
- 作成したリソーススクリプトを、リソースコンパイラ(rc.exe)でコンパイルしリソースファイルを作成する。
- リソースファイルをリンカ(link.exe)でリンクし、リソースDLLにする。
メッセージテキストファイルは以下の様な形式で記述します。
MessageId(これがイベントIDになります)を指定し、Severity(Success、Informational、Warning、Errorから選択します)を選び、言語毎のメッセージを記述します。
ここでは、 MyAppMessage.mc という名前でファイルを作成しておきます。
MessageIdTypedef=DWORD LanguageNames=(English=0x0409:MSG0409) LanguageNames=(Japanese=0x0411:MSG0411) MessageId=1 Language=English Category1 . Language=Japanese Category1 . MessageId=2 Language=English Category2 . Language=Japanese Category2 . MessageId=1000 Severity=Informational Language=English Message %1 . Language=Japanese メッセージは「%1」です。 . MessageId=1001 Severity=Warning Language=English Warning Message %1 . Language=Japanese 警告メッセージは「%1」です。 . MessageId=1002 Severity=Error Language=English Error Message %1 . Language=Japanese エラーメッセージは「%1」です。 .
メッセージテキストファイルの詳細はこちらをご覧ください http://msdn.microsoft.com/en-us/library/dd996906%28VS.85%29.aspx
メッセージテキストファイルを作成したら、メッセージコンパイラでコンパイルします。
mc.exe MyAppMessage.mc
コンパイルに成功すると以下のヘッダファイルとリソーススクリプトファイルが作成されます。
- MSG0409.bin
- MSG0411.bin
- MyAppMessage.h
- MyAppMessage.rc
リソーススクリプトが出来たら、リソースコンパイラでコンパイルします。
rc.exe MyAppMessage.rc
コンパイルに成功すると、以下のリソースファイルが作成されます。
- MyAppMessage.res
最後に、リソースをリンカでリンクします。リソースのみのDLLですので /NOENTRY オプションを指定します。
link.exe /NOENTRY /MACHINE:X86 /DLL MyAppMessage.res
これで、メッセージリソースDLL MyAppMessage.dll が出来上がります。
イベントソースの作成
メッセージDLLを作成したらイベントソースを作成し、イベントログのメッセージにこのDLLを使用する登録をする必要があります。
EventLog.CreateEventSource メソッドを使って以下の様に記述するとイベントソースの作成ができます。*1
using System.Diagnostics; EventSourceCreationData cd = new EventSourceCreationData("MyApp", "Application"); //イベントログのメッセージDLLの指定を行います cd.MessageResourceFile = @"C:\MyApp\MyAppMessage.dll"; //カテゴリのメッセージDLLの指定を行います cd.CategoryResourceFile = @"C:\MyApp\MyAppMessage.dll"; //カテゴリ数を指定します(今回の例では2になります) cd.CategoryCount = 2; //イベントソースの作成 EventLog.CreateEventSource(cd);
イベントソースの作成が成功すると、レジストリの HKLM\SYSTEM\CurrentControlSet\services\eventlog\Application\ にソース名の新しいキーが作成されます。
レジストリのキーが作成されていればイベントソースの作成は完了です。
イベントログの出力
ここまで来たらイベントログを出力する準備は完了ですので、EventLog.WriteEvent メソッドを使用して以下の様に記述することでメッセージDLLからメッセージを出力することが出来ます。
//カテゴリ指定なし、情報 EventLog.WriteEvent("MyApp", new EventInstance(0x400003E8L, //EventId:1000 0, //カテゴリ未指定 EventLogEntryType.Information), "情報"); //カテゴリ1、警告 EventLog.WriteEvent("MyApp", new EventInstance(0x800003E9L, //EventId:1001 1, //カテゴリ1 EventLogEntryType.Warning), "警告"); //カテゴリ2、エラー EventLog.WriteEvent("MyApp", new EventInstance(0xC00003EAL, //EventId:1002 2, //カテゴリ2 EventLogEntryType.Error), "エラー");
WriteEventメソッドの第一引数にはイベントソース名を指定します。
第二引数には EventInstanceクラスのインスタンスを指定するのですが、これがちょっと曲者で、コンストラクタの第一引数はInstanceIDとなっているのですが、ここにはリソーススクリプトを作成した時に出来た MyAppMessage.h に記述されているMessageIdを指定する必要あります。第二引数のCategoryIdも同様にMyAppMessage.hのMessageIdを指定します。第三引数にはEventLogEntryTypeを指定します。メッセージDLLのSeverityと違う区分にした場合はこの引数の値が優先される様です。*2
WriteEventの最後の引数にはメッセージパラメータを指定します。
イベントビューアで確認するとこんな感じで出力されます。
今回参考にしたサイト
http://www.monyo.com/technical/products/evt_messages/
http://d.hatena.ne.jp/kurip/20070117
http://msdn.microsoft.com/ja-jp/library/650k61tw(VS.80).aspx
http://msdn.microsoft.com/en-us/library/aa385646(VS.85).aspx
http://www.eventlogblog.com/blog/2008/04/event-log-message-files-the-de.html
http://re-thinkthings.spaces.live.com/blog/cns!1C5AE98DA3645F42!511.entry