前回はミニマムなプロバイダーを作りました。
しかし、あくまでイベント ビューアーで見るためのミニマム コードであって、ETW 的に本当に最小限のコードではありません。
今回は本当にミニマムなコードを示すとともに、(イベント ビューアーでは見ることができませんので)他のツールを紹介します。
コードは GitHub を参照してください。
マニフェスト以外は前回のコードからほとんど変わっていません。
ProviderManifest0.man
<?xml version="1.0" encoding="utf-8"?> <instrumentationManifest xmlns="http://schemas.microsoft.com/win/2004/08/events" xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <instrumentation> <events> <provider guid="{FF5D07C6-03BA-481F-B07F-97CB8A51FADF}" name="SampleProvider0" symbol="PROVIDERID_SampleProvider0" resourceFileName="Provider0.exe" messageFileName="Provider0.exe" parameterFileName="Provider0.exe"> <events> <event value="1" symbol="EVENTDESC_Hello"/> </events> </provider> </events> </instrumentation> </instrumentationManifest>
channel も template も stringTable も削りました。
ETW 的にはこれが最低限と言っていいでしょう。
もちろん、ちゃんと機能はします。
trace0.cmd
プロジェクトをビルドすると出力フォルダーに trace0.cmd というファイルができます。
logman create trace %name% -p %guid% -o "%~dp0%name%.etl" -ets Provider0.exe logman stop "%name%" -ets tracerpt "%~dp0%name%.etl" -o "%~dp0%name%.xml"
発行したイベントの確認にイベント ビューアーが使えませんので、別のツールを使います。
今回は logman と tracerpt というツールを使いました。どちらも Windows に標準で入っているツールです。
logman はコントローラーです。
create trace コマンドでトレース セッションを作成し、イベントを trace_test0.etl というファイルに保存します。
プロバイダー(Provider0.exe)がイベントを発行し終えたら、stop コマンドでセッションを停止します。
tracerpt はコンシューマーです。
trace_test0.etl ファイルは人間には読めないバイナリファイルなので、読みやすい xml 形式に変換します。
trace_test0.xml
trace0.cmd を実行すると作成される結果ファイルです。
注目して欲しいのは、RegisterProvider0.cmd でプロバイダーを登録していなくても、trace0.cmd は実行可能だということです。
試してみてください。
プロバイダーを登録していない場合の出力はこうなります。
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event"> <System> <Provider Guid="{ff5d07c6-03ba-481f-b07f-97cb8a51fadf}" /> <EventID>1</EventID> <Version>0</Version> <Level>0</Level> <Task>0</Task> <Opcode>0</Opcode> <Keywords>0x0</Keywords> <TimeCreated SystemTime="2014-10-06T18:44:43.260005800Z" /> <Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" /> <Execution ProcessID="20936" ThreadID="16692" ProcessorID="3" KernelTime="0" UserTime="0" /> <Channel /> <Computer /> </System> <BinaryEventData></BinaryEventData> </Event>
マニフェストで何も指定していないので、Version、Level、Task、Opcode、Keywords がすべて 0 になっています。
RegisterProvider0.cmd でプロバイダーを登録していると、こうなります。
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event"> <System> <Provider Name="SampleProvider0" Guid="{ff5d07c6-03ba-481f-b07f-97cb8a51fadf}" /> <EventID>1</EventID> <Version>0</Version> <Level>0</Level> <Task>0</Task> <Opcode>0</Opcode> <Keywords>0x0</Keywords> <TimeCreated SystemTime="2014-10-06T18:46:16.106633400Z" /> <Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" /> <Execution ProcessID="14284" ThreadID="5096" ProcessorID="3" KernelTime="0" UserTime="0" /> <Channel /> <Computer /> </System> <EventData> </EventData> <RenderingInfo Culture="ja-JP"> </RenderingInfo> </Event>
違いがわかるでしょうか。
登録していない場合、Event 要素には System 要素と BinaryEventData 要素が含まれます。
登録している場合は、System 要素、EventData 要素、RenderingInfo 要素が含まれています。
マニフェストを登録する作業は何のために必要かと言いますと、イベント データを解析するためなのです。
登録していない場合、単なるバイナリ データ(BinaryEventData)としてしか取得できません。
マニフェストがあると、もう少しわかりやすい形式で表示することができます。
ただし、今回は付随データを何も出力していないため、EventData 要素は空っぽです。
なお、System 要素の内容はどのプロバイダーでも同じなので、マニフェストがなくても解析できます。
次回予告
コントローラーとコンシューマーを作ってみましょうか。