おそらくプロジェクトにロギングツールを作成し、それを使用して診断が困難なバグを分析することに成功したと思われます。 しかし、あなたは常に状況に直面しました:
- ファイルに書き込むとき、コンソールはバグの再現性に劇的な影響を与えました。
- マルチ(プロセッサ/スレッド)アプリケーションがドライバーを頻繁に呼び出し、タイムスタンプとスレッドを一致させることができない場合。
- カスタムの側でバグが再生されると、teamviewerセッションは役に立たなくなり、さらに、デバッグシンボルのあるバージョンはプライベートになります。
- システムがロギングをディスクにドロップする時間がなくなる前にシステムアプリケーションがクラッシュした場合。
- または、ロギング用のマクロが次のように見える場合
#define TraceDbg(format, ...) \ printf( "(p %d, t %d) - (%s,%d) %s(): " format, GetCurrentProcessId(), GetCurrentThreadId(), __FILE__, __LINE__,__FUNCTION__, __VA_ARGS__ );
- ipaddrまたはUUIDを表示する別の方法を思いついたとき
この記事では、MSが提供するシステムアプリケーション用の最小限のオーバーヘッド診断ツールを備えた、高速で信頼性の高い多用途のデバッグツールであるWPPを紹介します。WPPについては、出版物「EventTrace for Windows。 ネットワークを介したドライバーデバッグメッセージの高速送信 。
ETWに基づいて、ロギングはオペレーティングシステムによって行われ、イベント識別子を使用し、独自の情報を含まず、システムラベルをイベント(時間、スレッド、プロセス、CPU)に自動的に追加します。 WPPロギングはリリースビルドに含まれているため、デバッグバージョンを再構築することなく、顧客側から情報を収集できます。
ETWの主要な用語は、 プロバイダー(イベントを記録するアプリケーション、 コントローラー)がデバッグセッションを制御し、 コンシューマーがセッション情報を読み取り可能な形式にフォーマットすることです。 以下の図は、コンポーネントの相互作用を示しています。

言葉から練習に移りましょう。 変更の例として、MSの公式サービス例-CppWindowsServiceを使用し、次の6点を使用して、ユースケースWPPトレースを検討します。
0. WPPをドライバーに追加する場合、新しいWDKにはプロジェクトテンプレートにWPPのアドインがあり、そのパラメーターは参照により利用できるため、ポイント1から読み取りを開始します 。 WppTracingSettings.propsプロパティファイルをリポジトリからコピーし、プロジェクトに手動で接続し、プロジェクトを閉じる前に新しいImportタグを追加します。
<Import Project="..\WppTracingSettings.props" /> </Project>
WppTracingSettings.propsにはWPPプリプロセッサコールが含まれ(ちなみに、cl.exeの前に起動するのでfuncを別のものでラップします)、プロジェクト名、ロギングマクロの名前とパラメーター、およびファイルのリスト(この場合はstdafxを除くすべて)を決定します。 cpp。
<ItemGroup> <TraceWppSources Include="@(ClCompile)" Exclude="stdafx.cpp" /> </ItemGroup> <Target Name="TraceWpp" BeforeTargets="ClCompile" Inputs="@(TraceWppSources)" Outputs="@(TraceWppSources -> '%(Filename).tmh')"> <Exec Command="cd $(ProjectDir)"/> <Exec Command="if not exist tmhs mkdir tmhs"/> <Message Importance="high" Text="Creating tmh"/> <Exec Command="$(BranchRoot)WppTracing\tracewpp.EXE -dll -func:TraceEvents(LEVEL,FLAGS,MSG,...) -p:$(ProjectName) -cfgdir:$(BranchRoot)WppTracing\wppconfig\rev1 -odir:tmhs @(TraceWppSources, ' ')" /> </Target>
Trey Nashの出版物に基づいています。
1.プロバイダーGUIDを生成するtracer.hを作成し、デバッグレベル(通常はevntrace.hから)とデバッグフラグを定義します。 私のプロジェクトでは、フラグを使用してモジュール(初期化、ディスパッチャプロシージャ、ロジックなど)を指定します。
#define WPP_CHECK_FOR_NULL_STRING //to prevent exceptions due to NULL strings #define WPP_CONTROL_GUIDS \ WPP_DEFINE_CONTROL_GUID(SimpleServiceProvider, (c34f5c45, 3569, 896c, ba85, bf8dcc85aa62), \ WPP_DEFINE_BIT(FLAG_INIT) /* bit 0 = 0x00000001 */ \ WPP_DEFINE_BIT(FLAG_TEST) /* bit 1 = 0x00000002 */ \ WPP_DEFINE_BIT(FLAG_OTHER) /* bit 2 = 0x00000004 */ \ WPP_DEFINE_BIT(FLAG_SERVICE) /* bit 3 = 0x00000008 */ \ /* You can have up to 32 defines. If you want more than that,\ you have to provide another trace control GUID */\ ) #define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) WPP_LEVEL_LOGGER(flags) #define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl)
2. WPPプリプロセッサによって生成されたファイルをcppファイルに含め、DllEntryまたはメインのWPP_INIT_TRACINGで呼び出して、システムにプロバイダーを登録し、トレースを呼び出します。
#include "tracer.h" #if defined(EVENT_TRACING) #include "tmhs/(I'm a filename).tmh" #endif void Sample(void) { // {4460B943-0D39-4627-B53D-5329E470BE86} static const GUID testGUID = { 0x4460b943, 0xd39, 0x4627, { 0xb5, 0x3d, 0x53, 0x29, 0xe4, 0x70, 0xbe, 0x86 } }; // Perform main service function here... TraceEvents(TRACE_LEVEL_INFORMATION, FLAG_INIT, "Test Fromat String %!GUID!", &testGUID); } int wmain(int argc, wchar_t *argv[]) { WPP_INIT_TRACING(NULL); Sample(); WPP_CLEANUP(); return 0; }
WPPには、いくつかの追加のフォーマット指定子が用意されており、独自に作成することもできます 。
3.プロバイダーが作成されました。次に、デバッグ情報セッションに接続する必要があります。 プロバイダーがシステム内のどのセッションにも属していない場合、TraceEventの呼び出しには1つの条件付きブランチのオーバーヘッドしかありません。
状況に最も適したコントローラーを使用して、プロバイダーのGUIDまたはPDBファイルを使用してセッションを作成します。 TraceViewは直観的です-私はそれにこだわることはありません。 リポジトリでは、StartTraceEtl.batおよびStopTrace.batスクリプトを使用して、etlファイルのLogmanコントローラーを起動できます。 logman updateを呼び出すことにより、セッションに2番目のプロバイダーを追加できます。
logman update testlog -p "{a34f5c45-3569-896c-ba85-bf8dcc85aa62}" 0xffff 0xff -rt -ets -o test.etl
同じセッション内の複数のプロバイダーのイベントは順番に記録され、各レコードはシーケンス番号に対応します。 下の画像のTraceViewで記録されたtest.etlセッションを開きます。

4. logmanはコントローラーにすぎず、TraceViewのようにロギングをその場でフォーマットすることはできません。 情報の収集を自動化する場合は、launch_wpp_log.batからlogmanを開始し、次にtracefmt.exe -rt testlog -display -p tmfpathを使用して、tracepdb.exeを使用して以前にtmfファイルを生成します。 tracefmtでは、構成ファイルを使用して表示形式を作成できます。 デフォルトの構成ファイルでの出力は次のとおりです。
Setting RealTime mode for testlog Examining C:\Users\user\Desktop\wpp\sample\WppTracing\default.tmf for message formats, 3 found. Searching for TMF files on path: C:\Users\user\Desktop\wpp\scripts\tmh [0]08FC.0100::10/15/2014-13:52:43.528 [CppWindowsService]CppWindowsService in OnStart [0]08FC.0F9C::10/15/2014-13:52:45.513 [CppWindowsService]Test Fromat String 175ms 4460b943-0d39-4627-b53d-5329e470be86 [0]08FC.0F9C::10/15/2014-13:52:47.525 [CppWindowsService]Test Fromat String 175ms 4460b943-0d39-4627-b53d-5329e470be86 [0]08FC.0F9C::10/15/2014
Windbgは、!Wmitrace拡張機能を使用してコントローラーとして機能することもできますが、私にとってはこの方法は機能しません。 代わりに、オプションのフラグTraceView-> Windbg Traceを使用します。
5. TMFファイルにはすべての文字列トレース定数が含まれており、ユーザーのマシンからデータを取得する必要がある場合、Tracefmtは修正された tmfファイルでも機能します。
// PDB: ..\Release\CppWindowsService.pdb // PDB: Last Updated :2014-10-10:12:12:25:166 (UTC) [tracepdb] 5ed21a20-2754-8ca0-11c6-9b60845d5180 CppWindowsService // SRC=1.cpp MJ= MN= #typev 1_cpp401 17 "%0Service failed to resume." // LEVEL=TRACE_LEVEL_INFORMATION FLAGS=FLAG_INIT FUNC=1::Continue { } // PDB: ..\Release\CppWindowsService.pdb // PDB: Last Updated :2014-10-10:12:12:25:166 (UTC) [tracepdb] 5ed21a20-2754-8ca0-11c6-9b60845d5180 CppWindowsService // SRC=ServiceBase.cpp MJ= MN= #typev servicebase_cpp401 17 "%0Service failed to resume." // LEVEL=TRACE_LEVEL_INFORMATION FLAGS=FLAG_INIT FUNC=CServiceBase::Continue { }
ソースコード、スクリプト、および必要なWPPユーティリティはこちらから入手できます 。
ハッピー