TraceLogging C/C++快速入門
下一節說明將 TraceLogging 新增至 C/C++使用者模式程式代碼所需的基本步驟。
先決條件
- Microsoft Visual Studio 2013 或更新版本。
- 需要 Windows 10 軟體開發工具套件 (SDK) 才能撰寫使用者模式提供者。
- 需要適用於 Windows 10 的 Windows 驅動程式套件 (WDK) 才能撰寫內核模式提供者。
重要
若要避免未解決 EventRegister
、EventWriteTransfer
或 EventUnregister
函式的連結器錯誤,請在編譯這些範例時與 advapi32.lib
連結。
若要從這些範例收集與解碼事件,您需要先使用類似 tracelog 或 traceview 的工具開始追蹤,然後執行範例,再使用類似 tracelog 或 traceview 的工具停止追蹤,最後使用 tracefmt 或 traceview 等解碼工具解碼追蹤。 例如,如果我的提供者是使用 GUID {0205c616-cf97-5c11-9756-56a2cee02ca7}
定義的,那麼我可能會使用 Windows SDK 工具 tracelog 和 tracefmt 查看這些範例中的事件,如下所示:
tracelog -start MyTraceSession -f MyTraceFile.etl -guid #0205c616-cf97-5c11-9756-56a2cee02ca7
- 執行範例。
tracelog -stop MyTraceSession
tracefmt -o MyTraceFile.txt MyTraceFile.etl
notepad MyTraceFile.txt
SimpleTraceLoggingExample.h
此範例標頭包含 TraceLogging API,並轉送宣告將用於記錄事件的提供程式控制代碼。 任何想要使用 TraceLogging 的類別都會包含此標頭,然後可以開始記錄。
#pragma once
#include <windows.h> // Definitions required by TraceLoggingProvider.h
#include <TraceLoggingProvider.h> // The C/C++ TraceLogging API
// Forward-declare the g_hMyComponentProvider variable that you will use for tracing in this component
TRACELOGGING_DECLARE_PROVIDER(g_hMyComponentProvider);
頭檔包含定義 C/C++ TraceLogging API 的 TraceLoggingProvider.h
。 您必須先包含 windows.h
,因為它會定義 TraceLoggingProvider.h
所使用的常數。
轉送的頭檔會宣告提供者句柄 g_hMyComponentProvider
,您將傳遞給 TraceLogging API 以記錄事件。 此句柄必須可供任何想要使用 TraceLogging 的程式代碼存取。
TRACELOGGING_DECLARE_PROVIDER 是一個巨集,使用您提供的名稱來建立 extern const TraceLoggingHProvider
句柄,如範例中所示為 g_hMyComponentProvider
。
您會在程式代碼檔案中設定實際的提供者句柄變數。
SimpleTraceLoggingExample.cpp
下列範例會註冊提供者、記錄事件,以及取消註冊提供者。
#include "SimpleTraceLoggingExample.h"
// Define a handle to a TraceLogging provider
TRACELOGGING_DEFINE_PROVIDER(
g_hMyComponentProvider,
"SimpleTraceLoggingProvider",
// {0205c616-cf97-5c11-9756-56a2cee02ca7}
(0x0205c616,0xcf97,0x5c11,0x97,0x56,0x56,0xa2,0xce,0xe0,0x2c,0xa7));
void main()
{
char sampleValue[] = "Sample value";
// Register the provider
TraceLoggingRegister(g_hMyComponentProvider);
// Log an event
TraceLoggingWrite(g_hMyComponentProvider, // handle to my provider
"HelloWorldTestEvent", // Event Name that should uniquely identify your event.
TraceLoggingValue(sampleValue, "TestMessage")); // Field for your event in the form of (value, field name).
// Stop TraceLogging and unregister the provider
TraceLoggingUnregister(g_hMyComponentProvider);
}
上述範例包含 SimpleTraceLoggingExample.h,其中包含程式代碼將用來記錄事件的全域提供者變數。
TRACELOGGING_DEFINE_PROVIDER 巨集會配置記憶體,並定義提供者控制碼變數。 您提供給此宏的變數名稱必須與您在標頭檔中使用的 TRACELOGGING_DECLARE_PROVIDER 宏的名稱一致。
註冊提供者識別碼
您必須先呼叫 TraceLoggingRegister,以註冊您的提供者句柄,然後才能使用該句柄來記錄事件。 這通常是在main() 或 DLLMain() 中完成,但只要在每次嘗試記錄事件之前即可完成。 如果您在註冊提供者控制代碼之前記錄事件,則不會發生錯誤,但事件不會被記錄。 上述範例中的下列程式代碼會註冊提供者句柄。
// Define the GUID to use in TraceLoggingProviderRegister
TRACELOGGING_DEFINE_PROVIDER(
g_hMyComponentProvider,
"SimpleTraceLoggingProvider",
// {0205c616-cf97-5c11-9756-56a2cee02ca7}
(0x0205c616,0xcf97,0x5c11,0x97,0x56,0x56,0xa2,0xce,0xe0,0x2c,0xa7));
void main()
{
char sampleValue[] = "Sample value";
// Register the provider
TraceLoggingRegister(g_hMyComponentProvider);
記錄 Tracelogging 事件
註冊提供者之後,下列程式代碼會記錄簡單的事件。
// Log an event
TraceLoggingWrite(g_hMyComponentProvider, // handle to my provider
"HelloWorldTestEvent", // Event Name that should uniquely identify your event.
TraceLoggingValue(sampleValue, "TestMessage")); // Field for your event in the form of (value, field name).
TraceLoggingWrite 巨集最多可以接受九十九個參數。 事件名稱會以UTF-8格式儲存。 您不得在事件名稱或功能變數名稱中使用內嵌 '\0'
字元。 允許的字元沒有其他限制,不過某些事件譯碼器或事件處理器可能有自己的限制。
事件名稱後面的每個引數都必須包裝在 TraceLogging 包裝函式巨集。 如果您使用 C++,您可以使用 TraceLoggingValue
包裝函式巨集來自動推算自變數的類型。 如果您要以 C 撰寫,或想要對欄位類型進行更多控制,則必須使用類型特定的欄位巨集,例如 TraceLoggingInt32
、TraceLoggingUnicodeString
、TraceLoggingString
等。
除了記錄單一事件之外,您也可以使用 TraceLoggingWriteActivity 或 TraceLoggingWriteStart/TraceLoggingWriteStop 巨集,通過活動來分組事件,這些巨集可以在 TraceLoggingActivity.h 中找到。 活動會讓事件相互關聯,而且對於開頭和結尾的案例很有用。 例如,您可以使用一個活動來測量一個場景,該場景從應用程式的啟動畫面開始,包括啟動畫面出現所需的時間,直至應用程式的初始畫面顯示為止。
活動會擷取單一事件,並嵌入到該活動開始和結束之間發生的其他活動。 活動具有每個進程的範圍,而且必須在線程之間傳遞,以正確地嵌套多線程事件。
提供者句柄的範圍僅限於定義提供者句柄的模組 (DLL、EXE 或 SYS 檔案)。 句柄不應該傳遞給其他 DLL。 如果在 A.DLL 中使用 B.DLL 定義的提供者句柄叫用 TraceLoggingWrite 宏,可能會導致問題。 最安全且最有效率的方式來符合這項需求,就是一律直接參考全域提供者句柄,而且絕不會傳遞提供者句柄做為參數。
取消註冊提供者
在元件卸除之前,您必須取消註冊 TraceLogging 提供者。 對於 DLL 和驅動程式而言,這特別重要。 如果 DLL 或驅動程式在未註冊提供者的情況下卸除,就可能會當機。
下列程式代碼會取消註冊提供者:
// Stop TraceLogging and unregister the provider
TraceLoggingUnregister(g_hMyComponentProvider);
相容性
視其設定而定,TraceLoggingProvider.h 可以回溯相容(產生的程式將在Windows Vista 或更新版本上執行),也可以針對較新的 OS 版本進行優化。 TraceLoggingProvider.h 使用 WINVER (使用者模式) 和 NTDDI_VERSION (kernel-mode) 來判斷它是否應該與舊版作系統相容,還是針對較新的 OS 版本進行優化。
針對使用者模式,如果您在設定WINVER之前包含 <windows.h>
,<windows.h>
將 WINVER 設定為 SDK 的預設目標 OS 版本。 如果WINVER設定為0x602或更新版本,TraceLoggingProvider.h
針對Windows 8或更新版本優化其行為,且您的應用程式不會在舊版 Windows 上執行。 如果您需要在 Vista 或 Windows 7 上執行程式,請務必在包含 <windows.h>
之前,將 WINVER 設定為適當的值。
同樣地,如果您在設定NTDDI_VERSION之前包含 <wdm.h>
,<wdm.h>
會將NTDDI_VERSION設為預設值。 如果NTDDI_VERSION設定為 0x06040000 或更高版本,TraceLoggingProvider.h 會針對 Windows 10 優化其行為,而您的驅動程式將無法在舊版 Windows 上運作。
在包含 TraceLoggingProvider.h
之前設定 TLG_HAVE_EVENT_SET_INFORMATION
,可以控制此行為的方向。
如需 TLG_HAVE_EVENT_SET_INFORMATION
巨集的詳細數據,請參閱 TraceLoggingProvider.h
標頭中的批註。
摘要和後續步驟
若要瞭解如何使用 Windows 效能工具擷取和檢視 TraceLogging 數據,請參閱 記錄和顯示 TraceLogging 事件。
如需更多C++ TraceLogging 範例,請參閱 C/C++ Tracelogging 範例。