イベントログで使うメッセージファイル DLLを作成する

Windows Vista & 2008 では新しいイベントログ システムにバージョンアップしました。
Windows Event Log という名前になっています。
従来のイベントログは、*.evt という形式で保存されていましたが、Windows Event Log では
*.evtx という XML 形式で保存されています。
また、サブスクライバモデルが導入されているため、イベントログを別の Windows に転送することも
できちゃいます。便利ですね~。でも、今回のネタは新機能ではなく、従来からの SDK ネタです。
ちょっと古いような気もしますが、まだまだ需要はあると思います。
MSDN のイベントログに関する内容は

にあります。ぜひ、参照してみてください。
プログラムでイベントログにイベントを出力する際には

BOOL ReportEvent(
  HANDLE hEventLog,    // イベントログのハンドル
  WORD wType,          // ログに書き込むイベントの種類
  WORD wCategory,      // イベントの分類
  DWORD dwEventID,     // イベント識別子
  PSID lpUserSid,      // ユーザーセキュリティ識別子(省略可能)
  WORD wNumStrings,    // メッセージにマージする文字列の数
  DWORD dwDataSize,    // バイナリデータのサイズ(バイト数)
  LPCTSTR *lpStrings,  // メッセージにマージする文字列の配列
  LPVOID lpRawData     // バイナリデータのアドレス
);

という API を使用します。この API を使って、書き出したい文字列を渡してもいいのですが
多国語対応するときには、ちょっと面倒です。そのため、イベントログでは、メッセージファイルという専用の
バイバリリソースを持つことで言語をニュートラルにすることができます。
今回は、そのメッセージファイルを作成してみます。

まずは、全体の流れです。

メッセージDLL作成

1. メッセージファイルの作成

拡張子 mc というメッセージファイル(テキストファイル)を作成します。
どのような構文なのかは、以下の URL を参考にしてください。

今回は、EventlogMsg.mc というファイルを作成します。
このファイルで英語と日本語のメッセージをサポートしてみます。

; // ***** EventlogMsg.mc *****
; // This is the header section.MessageIdTypedef=DWORDSeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS
    Informational=0x1:STATUS_SEVERITY_INFORMATIONAL
    Warning=0x2:STATUS_SEVERITY_WARNING
    Error=0x3:STATUS_SEVERITY_ERROR
    )FacilityNames=(System=0x0:FACILITY_SYSTEM
    Runtime=0x2:FACILITY_RUNTIME
    Stubs=0x3:FACILITY_STUBS
    Io=0x4:FACILITY_IO_ERROR_CODE
)LanguageNames=(English=0x409:MSG00409)
LanguageNames=(Japanese=0x411:MSG00411); // The following are message definitions.MessageId=0x1
Severity=Error
Facility=Runtime
SymbolicName=MSG_BAD_COMMAND
Language=English
You have chosen an incorrect command.
.
Language=Japanese
誤ったコマンドが選択されました。
.
MessageId=0x2
Severity=Warning
Facility=Io
SymbolicName=MSG_BAD_CONN
Language=English
Cannot connect to the server.
.
Language=Japanese
サーバーに接続できません。
.
MessageId=0x3
Severity=Error
Facility=System
SymbolicName=MSG_CMD_DELETE
Language=English
File %1 contains %2 which is in error
.
Language=Japanese
ファイル %1 にエラーはある %2 が含まれています。
.
MessageId=0x4
Severity=Informational
Facility=System
SymbolicName=MSG_RETRYS
Language=English
There have been %1!d! attempts with %2!d!%% success%! Disconnect from the server and try again later.
.
Language=Japanese
%1!d! 回再試行し、%2!d!%% 回成功しました %! サーバーから切断してから再試行してください。
.

メッセージファイルを作成する際の注意事項ですが、メッセージの区切り「.(ピリオド)」を正しく入力してください
後ろにスペースがあったりすると、メッセージコンパイラでコンパイルエラーになります。

2. メッセージコンパイラでコンパイルする

1. で作成したメッセージファイルをコンパイルします。
Visual Studio をインストールすると、メッセージコンパイラ(MC.EXE)がインストールされます。[スタートメニュー]-[Microsoft Visual Studio 2008]-[Visual Studio Tools]にある「Visual Studio 2008 コマンド プロンプト」を開いてみます。

mc

そのコマンドプロンプトで mc と入力してみてください。

パラメーターが必要なことがわかります。
今回は、

mc -s -U EventlogMsg.mc

というコマンドを入力します。すると

  • MSG00409.bin
  • MSG00411.bin
  • EventlogMsg.h
  • EventlogMsg.rc

という 4 つのファイルが生成されます。

3. Visual Studio で DLL を作成する ここまで来たら、あとは、DLL を作成するだけです。

EventlogMsg_プロジェクト作成1

EventlogMsg_プロジェクト作成2

ここに先ほど作成された 4つのファイルをプロジェクトのソースがあるところにコピーしておきます。
そして、プロジェクトに EventlogMsg.h と EventlogMsg.rc を追加します。
bin ファイルはバイナリファイルなので、プロジェクトに追加する必要はありません。
これで DLL のビルドを行えば完成なのですが、その前に少しだけチューニングします。
まず、この DLL は、メッセージリソースファイルだけの DLL にしたいので、
リンカの設定で「エントリポイントなし」「はい」にしておきます。(/NOENTRY の設定)

リンカの設定1

次にマニフェストも必要ないので「マニフェストの生成」「いいえ」「埋め込みマニフェスト」「いいえ」にしておきます。

リンカの設定2

リンカの設定3

これですべて準備完了です。ビルドしてみると、EventlogMsg.dll ができます。では、本当にメッセージ DLL ができたのか
確認してみます。
何か適当なリソースエディタでビルドした DLL を開いてください。(今回は Resource Hacker を使ってみます)

ResHac_メッセージ確認

きちんとリソースとしてメッセージができていますね。
あとはアプリケーションから ReportEvent() を使い、イベントログに書き込めばいいわけです。

メッセージファイルをレジストリ登録するのをお忘れなく。

それでは。

One Response to イベントログで使うメッセージファイル DLLを作成する

  1. ピンバック: Ruby スクリプトから Windows Server のイベントログにログを送る雑なメモ(2)〜 メッセージファイルを作成してメッセージ ID をレジストリに登録する等 〜 | cloudpack.media

コメントを残す