共用方式為


TraceLogging C/C++快速入門

下一節說明將 TraceLogging 新增至 C/C++使用者模式程式代碼所需的基本步驟。

先決條件

  • Microsoft Visual Studio 2013 或更新版本。
  • 需要 Windows 10 軟體開發工具套件 (SDK) 才能撰寫使用者模式提供者。
  • 需要適用於 Windows 10 的 Windows 驅動程式套件 (WDK) 才能撰寫內核模式提供者。

重要

若要避免未解決 EventRegisterEventWriteTransferEventUnregister 函式的連結器錯誤,請在編譯這些範例時與 advapi32.lib 連結。

若要從這些範例收集與解碼事件,您需要先使用類似 tracelog 或 traceview 的工具開始追蹤,然後執行範例,再使用類似 tracelog 或 traceview 的工具停止追蹤,最後使用 tracefmt 或 traceview 等解碼工具解碼追蹤。 例如,如果我的提供者是使用 GUID {0205c616-cf97-5c11-9756-56a2cee02ca7}定義的,那麼我可能會使用 Windows SDK 工具 tracelogtracefmt 查看這些範例中的事件,如下所示:

  • 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 撰寫,或想要對欄位類型進行更多控制,則必須使用類型特定的欄位巨集,例如 TraceLoggingInt32TraceLoggingUnicodeStringTraceLoggingString等。

除了記錄單一事件之外,您也可以使用 TraceLoggingWriteActivityTraceLoggingWriteStart/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 範例