将 WPP 软件跟踪添加到 Windows 驱动程序

若要在跟踪提供程序(如内核模式驱动程序或用户模式应用程序)中使用 WPP 软件跟踪,需要添加代码 (或 检测) 驱动程序源文件并修改驱动程序项目。 本部分将介绍这些步骤。

提示 将 WPP 跟踪添加到驱动程序的最简单方法是在 Visual Studio 中使用 KMDF 或 UMDF 驱动程序模板之一。 如果使用模板,需要添加的大部分代码已经为你完成。 在 Visual Studio 中,选择“ 文件 > 新建 > 项目”,然后选择 Windows 驱动程序 (用户模式或内核模式) WDF 项目。 WPP 宏在作为项目一部分包含的 Trace.h 头文件中定义。 如果使用其中一个模板,可以跳到 步骤 5

步骤 1:定义控件 GUID 和跟踪标志

每个跟踪提供程序 ((如驱动程序或用户模式应用) )都必须唯一定义。 为此,可以添加定义控件 GUID、标识符和跟踪标志 的 WPP_CONTROL_GUIDS 宏。 这样做是为了确定和控制要跟踪的时间和内容。 虽然每个驱动程序通常都有一个单独的控件 GUID,但一个驱动程序可以有多个控件 GUID,或者多个驱动程序可以共享一个控件 GUID。

为方便起见, WPP_CONTROL_GUIDS 宏通常在通用头文件中定义。 头文件必须包含在要检测用于跟踪的任何源文件中 (#include) 。

若要向驱动程序添加WPP_CONTROL_GUIDS宏,请执行以下操作:

  1. 向 Visual Studio 项目添加新的 C++ 头文件,可用于定义 WPP 跟踪宏。 例如,选择并按住 (,或者右键单击) 解决方案资源管理器中的驱动程序,然后选择“添加新>项”。 将文件 (保存为 Trace.h,例如) 。

  2. 添加 WPP_CONTROL_GUIDS 宏以指定跟踪提供程序的友好名称、定义控件 GUID 以及定义可用于限定特定跟踪消息的跟踪标志。

    WPP_CONTROL_GUIDS 宏具有以下语法:

    WPP_CONTROL_GUIDS语法

    #define WPP_CONTROL_GUIDS \
        WPP_DEFINE_CONTROL_GUID(GUIDFriendlyName, (ControlGUID),  \
            WPP_DEFINE_BIT(NameOfTraceFlag1)  \
            WPP_DEFINE_BIT(NameOfTraceFlag2)  \
            .............................   \
            .............................   \
            WPP_DEFINE_BIT(NameOfTraceFlag31) \
            )
    

    例如,以下代码使用 myDriverTraceGuid 作为 GUIDFriendlyName。 请注意, ControlGUID 的格式与 32 位十六进制 GUID 的标准格式略有不同。 ControlGUID 有五个字段,但它们用逗号分隔,用括号括起来,而不是通常的连字符和大括号。 例如,指定 ( (84bdb2e9,829e,41b3,b891,02f454bc2bd7) 而不是 {84bdb2e9-829e-41b3-b891-02f454bc2bd7}。

    WPP_CONTROL_GUIDS 语句的示例

    #define WPP_CONTROL_GUIDS                                              \
        WPP_DEFINE_CONTROL_GUID(                                           \
            myDriverTraceGuid, (84bdb2e9,829e,41b3,b891,02f454bc2bd7), \
            WPP_DEFINE_BIT(MYDRIVER_ALL_INFO)        /* bit  0 = 0x00000001 */ \
            WPP_DEFINE_BIT(TRACE_DRIVER)             /* bit  1 = 0x00000002 */ \
            WPP_DEFINE_BIT(TRACE_DEVICE)             /* bit  2 = 0x00000004 */ \
            WPP_DEFINE_BIT(TRACE_QUEUE)              /* bit  3 = 0x00000008 */ \
            )                             
    

    提示 可以将此代码片段复制到头文件中。 请务必更改控件 GUID 和友好名称。 可以使用 GUIDgen.exe 生成控件 GUID。 Guidgen.exe包含在 Visual Studio (Tools > Create GUID) 中。 还可以使用 Uuidgen.exe 工具,该工具可从 Visual Studio 命令提示符窗口 (键入 uuidgen.exe /? 以获取) 的详细信息。

  3. 定义 跟踪提供程序的跟踪标志

    WPP_CONTROL_GUIDS 宏的WPP_DEFINE_BIT元素定义跟踪提供程序的跟踪标志。 通常,标志表示越来越详细的报告级别,但你可以根据需要以任何方式使用标志作为生成跟踪消息的条件。 在WPP_CONTROL_GUIDS示例中,WPP_DEFINE_BIT定义了四个跟踪标志 (MYDRIVER_ALL_INFO、TRACE_DRIVER、TRACE_DEVICE和TRACE_QUEUE) 。

    最多可以定义 31 个跟踪标志。 WPP 按元素的出现顺序为元素分配位值,例如,位 0 (0x1) 、位 1 (0x2) 、位 2 (0x4) 、3 位 (0x8) 等。 (步骤 5:检测驱动程序代码中所述,将跟踪消息函数添加到源代码时 使用跟踪标志,以在) 的适当点生成跟踪消息

    注意 使用跟踪标志,可以控制何时跟踪特定组件 (例如,特定 I/O 请求或设备或驱动程序对象的活动) 。 将跟踪标志添加到跟踪消息语句 (例如 DoTraceMessage (TRACE_DRIVER, "Hello World!\n")。 使用跟踪控制器(如 Tracelog)创建跟踪会话时,可以指定用于该会话中的跟踪提供程序的 -flag 选项,在本例中,标志为 1 位 (0x1) ,对应于TRACE_DRIVER标志。 启动跟踪会话时,指定跟踪标志的所有跟踪消息都会写入日志。

步骤 2:选择要使用的跟踪消息函数,并为这些函数定义 WPP 宏

与调试打印函数一样,跟踪消息函数是添加到代码以编写跟踪消息 (或宏) 函数。

选择跟踪消息函数

  1. 默认跟踪消息函数是 DoTraceMessage 宏。 如果使用默认函数,则可以使用提供程序的 跟踪标志 值来控制何时生成消息。 跟踪标志值是在步骤 1 中创建控件 GUID 时定义的标志。 如果使用 DoTraceMessage,则默认 WPP 宏已定义 (WPP_LEVEL_ENABLED和WPP_LEVEL_LOGGER) ,因此可以跳过此步骤的其余部分,转到 步骤 5

  2. 如果使用 KMDF 或 UMDF 模板之一,则 TraceEvents 函数和必要的 WPP 宏已定义以启用该函数,因此可以跳到 步骤 5

  3. 如果要创建自己的跟踪消息函数或转换现有的调试打印函数,请继续执行此步骤的其余部分。

创建或自定义跟踪消息函数

  1. 如果使用自定义跟踪消息函数,或者想要将调试打印函数 (例如 KdPrint) 来生成跟踪消息,则需要定义 WPP 宏,用于在跟踪提供程序中标识和启用跟踪消息函数。 将这些宏放入添加到项目的 Trace.h 头文件中。

  2. 定义 WPP 宏以启用跟踪函数。

    使用的每个跟踪消息函数都必须具有相应的宏对。 这些宏标识跟踪提供程序并指定生成消息的条件。 通常定义一对宏, WPP_<条件>_LOGGERWPP_<条件>_ENABLED 默认WPP_LEVEL_ENABLED和WPP_LEVEL_LOGGER宏。

使用的每个跟踪消息函数都必须具有相应的宏对。 这些宏标识跟踪提供程序并指定生成消息的条件。 通常定义一对宏, WPP_<条件>_LOGGERWPP_<条件>_ENABLED 默认WPP_LEVEL_ENABLED和WPP_LEVEL_LOGGER宏。

术语 说明

WPP_CONDITIONS_LOGGER

用于查找与提供程序关联的跟踪会话,并返回会话的句柄。

WPP_CONDITIONS_ENABLED

用于确定是否使用指定的条件启用日志记录。

对于定义的 WPP 宏, “条件” 表示跟踪消息函数支持的条件,其出现在函数的参数列表中的顺序用下划线分隔。 例如,默认跟踪消息函数 DoTraceMessage 仅支持 跟踪标志 作为条件,因此宏名称中只有一个参数 (WPP_LEVEL_ENABLED) 。

注意 遗憾的是, (WPP_LEVEL_ENABLED 和 WPP_LEVEL_LOGGER) 的默认宏的名称似乎表示 跟踪级别 参数,但它们实际上引用了跟踪标志。

如果使用自定义跟踪消息函数,则可以设置其他限定符,例如 跟踪级别。 跟踪级别在 Evntrace.h 文件中定义,跟踪级别提供了一种将跟踪消息分类为错误、警告和信息性消息的便捷方法。

例如,可以将以下代码片段添加到添加到项目的头文件。 以下代码为跟踪消息函数定义自定义 WPP 宏,该函数支持将 跟踪级别 和跟踪标志参数作为生成跟踪消息的条件。 如果为指定的 FLAGS 值启用了日志记录,并且启用的 LEVEL 值大于或等于跟踪消息函数调用中使用的 level 参数,则 WPP_LEVEL_FLAGS_ENABLED 宏将返回 TRUE。

#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)

接下来,需要在 WPP 配置块中指定自定义跟踪函数, (begin_wpp配置end_wpp) 例如,如果在 Visual Studio 中使用用于 UMDF 或 KMDF 驱动程序项目的模板,则模板会为名为 TraceEvents 的自定义跟踪消息函数定义 WPP 宏。 TraceEvents 宏函数使用跟踪级别和跟踪标志作为生成消息的条件。 如果已在 Trace.h 头文件中定义了 WPP_LEVEL_FLAGS_ENABLED 宏,则可以添加以下宏定义。

//
// This comment block is scanned by the trace preprocessor to define the 
// TraceEvents function.
//
// begin_wpp config
// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
// end_wpp
//

还可以通过在 WPP 配置块中添加类似的 FUNC 声明,将现有的调试打印语句转换为跟踪消息语句。 例如,以下示例添加代码以转换现有的 KdPrint 语句。 FUNC 声明还全局定义 KdPrint 以使用指定的跟踪级别和标志 {LEVEL=TRACE_LEVEL_INFORMATION, FLAGS=TRACE_DRIVER}。 调试打印语句将发送到跟踪日志,而不是将输出发送到调试器。

//
// This comment block is scanned by the trace preprocessor to define the
// TraceEvents function and conversion for KdPrint. Note the double parentheses for the KdPrint message, for compatiblility with the KdPrint function.
//
// begin_wpp config
// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
// FUNC KdPrint{LEVEL=TRACE_LEVEL_INFORMATION, FLAGS=TRACE_DRIVER}((MSG, ...));
// end_wpp
//

注意 如果要将 KdPrintEx 转换为跟踪消息函数,则需要执行一些额外的步骤。 与 KdPrint 相比, KdPrintEx 函数采用两个附加参数。 若要转换 KdPrintEx 函数,需要为 ComponentID 定义WPP_DEFINE_BIT,并定义自定义WPP_<条件>_LOGGERWPP_<条件>_ENABLED宏。 KdPrintEx 的第二个参数指定 的级别类似于跟踪级别值,因此无需重新定义它们。


#define WPP_CONTROL_GUIDS                                              \
    WPP_DEFINE_CONTROL_GUID(\
    myDriverTraceGuid, (11C3AAE4, 0D88, 41b3, 43BD, AC38BF747E19), \    /* change GUID for your provider */
        WPP_DEFINE_BIT(MYDRIVER_ALL_INFO)        /* bit  0 = 0x00000001 */ \
        WPP_DEFINE_BIT(TRACE_DRIVER)             /* bit  1 = 0x00000002 */ \
        WPP_DEFINE_BIT(TRACE_DEVICE)             /* bit  2 = 0x00000004 */ \
        WPP_DEFINE_BIT(TRACE_QUEUE)              /* bit  3 = 0x00000008 */ \
        WPP_DEFINE_BIT(DPFLTR_IHVDRIVER_ID)      /* bit  4 = 0x00000010 */\         /* Added for the ComponentID param of KdPrintEx */
    )

#define WPP_Flags_LEVEL_LOGGER(Flags, level)                                  \
    WPP_LEVEL_LOGGER(Flags)

#define WPP_Flags_LEVEL_ENABLED(Flags, level)                                 \
    (WPP_LEVEL_ENABLED(Flags) && \
    WPP_CONTROL(WPP_BIT_ ## Flags).Level >= level)



//
// This comment block is scanned by the trace preprocessor to convert the KdPrintEx function.
// Note the double parentheses for the KdPrint message, for compatiblility with the KdPrintEx function.
//
// begin_wpp config
// FUNC KdPrintEx((Flags, LEVEL, MSG, ...));   
// end_wpp
//

步骤 3:将关联的跟踪头文件 (.h 和 .tmh) 包含在 C 或 C++ 源文件中

如果在头文件中为驱动程序定义了控制 GUID 和跟踪标志, (例如 trace.h) ,则需要将头文件包含在源文件中,你将在其中初始化和卸载 WPP (步骤 4) 或调用跟踪消息函数。

此外,还需要为跟踪消息头文件 (.tmh) 添加#include语句。 生成驱动程序或应用程序时,WPP 预处理器会为每个包含跟踪消息函数的源文件生成跟踪消息头文件 (.tmh) 。

/* -- driver.c  - include the *.tmh file that is generated by WPP --*/

#include "trace.h"     /* file that defines WPP_CONFIG_GUIDS and trace flags */
#include "driver.tmh"  /* this file is auto-generated */

步骤 4:向相应的回调函数添加宏以初始化和清理 WPP

在驱动程序条目上初始化 WPP

  • WPP_INIT_TRACING 宏添加到内核模式驱动程序或 UMDF 2.0 驱动程序的 DriverEntry 例程,或添加到用户模式驱动程序的 DLLMain 例程 (UMDF 1.x) 或应用程序。

在驱动程序退出时清理 WPP 资源

  • WPP_CLEANUP 宏添加到驱动程序卸载例程 (例如内核模式驱动程序或 UMDF 2.0 驱动程序的 DriverContextCleanupDriverUnload) 。

    对于用户模式驱动程序 (UMDF 1.x) 或应用程序,请将 WPP_CLEANUP 宏添加到 DLLMain 例程。

    还应将 WPP_CLEANUP 宏添加到 DriverEntry 例程,以防 DriverEntry 失败。 例如,如果 DriverEntry 失败,则不会调用驱动程序卸载例程。 请参阅以下示例中对 WdfDriverCreate 的 调用。

DriverEntry 中使用 WPP_INIT_TRACING 和 WPP_CLEANUP 的内核模式驱动程序示例


NTSTATUS
DriverEntry(
    _In_ PDRIVER_OBJECT  DriverObject,
    _In_ PUNICODE_STRING RegistryPath
    )
{  

          //  ... 

                //
    // Initialize WPP Tracing in DriverEntry
    //
    WPP_INIT_TRACING( DriverObject, RegistryPath );

                //  ...


 //
    // Create a framework driver object to represent our driver.
    //
    status = WdfDriverCreate(
        DriverObject,
        RegistryPath,
        &attributes, // Driver Object Attributes
        &config,          // Driver Config Info
        WDF_NO_HANDLE // hDriver
        );

    if (!NT_SUCCESS(status)) {

        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,
                "WdfDriverCreate failed with status 0x%x\n", status);
        //
        // Cleanup tracing here because DriverContextCleanup will not be called
        // as we have failed to create WDFDRIVER object itself.
        // Please note that if you return failure from DriverEntry after the
        // WDFDRIVER object is created successfully, you don't have to
        // call WPP cleanup because in those cases DriverContextCleanup
        // will be executed when the framework deletes the DriverObject.
        //
        WPP_CLEANUP(DriverObject);

    }

                return status;

}

在 DriverContextCleanup 中使用 WPP_CLEANUP 的内核模式驱动程序示例



VOID
DriverContextCleanup(
       PDRIVER_OBJECT DriverObject
       )
{
    // ...

    // Clean up WPP resources on unload
    //
    WPP_CLEANUP(DriverObject);

   // ...

}

在 DriverEntry 中使用 WPP_INIT_TRACING 的 UMDF 2.0 驱动程序示例


/
// Driver specific #defines in trace header file (trace.h)
//
#define MYDRIVER_TRACING_ID      L"Microsoft\\UMDF2.0\\UMDF2_0Driver1 V1.0"

 // Initialize WPP Tracing in the DriverEntry routine
 //
    WPP_INIT_TRACING( MYDRIVER_TRACING_ID );

UMDF 1.0 驱动程序在 DLLMain 中使用 WPP_INIT_TRACING 和 WPP_CLEANUP 宏的示例

/
// Driver specific #defines in trace header file (for example, trace.h)
//
#define MYDRIVER_TRACING_ID      L"Microsoft\\UMDF1.X\\UMDF1_XDriver1"


//
// DLL Entry Point - UMDF 1.0 example in the source file where you implement the DLL exports.
// 

extern "C"
BOOL
WINAPI
DllMain(
    HINSTANCE hInstance,
    DWORD dwReason,
    LPVOID lpReserved
    )
{
    if (dwReason == DLL_PROCESS_ATTACH) {
        WPP_INIT_TRACING(MYDRIVER_TRACING_ID);              // Initialize WPP tracing

        g_hInstance = hInstance;
        DisableThreadLibraryCalls(hInstance);

    } else if (dwReason == DLL_PROCESS_DETACH) {
        WPP_CLEANUP();                                                                                                              // Deactivate and cleanup WPP tracing
    }

    return _AtlModule.DllMain(dwReason, lpReserved);
}

步骤 5:检测驱动程序代码以在适当点生成跟踪消息

可以使用所选的任何跟踪消息函数,前提是跟踪消息函数、跟踪标志和级别已正确定义。 默认跟踪消息函数是 DoTraceMessage 宏。 可以将此宏添加到代码中,以便将消息写入日志文件。 下表列出了一些预定义的跟踪消息函数以及可用于创建跟踪消息的调试打印函数。

示例跟踪消息函数 何时使用
DoTraceMessage

这是默认的跟踪消息函数。 使用 DoTraceMessage 的优点是已为你定义了函数。 可以使用在 WPP_CONFIG_GUIDS 宏中指定的跟踪标志。 使用 DoTraceMessage 的缺点是函数仅采用一个条件参数,即跟踪标志。 如果要使用跟踪级别,若要仅记录错误或警告消息,可以使用 DoDebugTrace 宏,也可以使用 TraceEvents,它同时使用跟踪标志和跟踪级别。

TraceEvents

如果在 Visual Studio 中使用 WDF 模板创建驱动程序,则这是默认的跟踪消息函数。 使用 TraceEvents 的优点是已经为你定义了跟踪消息函数、跟踪标志和 跟踪级别 。 此外,这些模板还包括检测,用于在函数进入和退出时将消息写入日志文件。

KdPrintKdPrintExDbgPrintDbgPrintEx

使用调试打印函数的优点是,无需修改现有的调试打印语句。 可以轻松地从在调试器中查看消息切换到在文件中记录跟踪消息。 如果将跟踪消息函数自定义为包含调试打印函数之一,则无需执行任何其他工作。 使用 Logman、 Tracelog 或其他跟踪控制器创建跟踪会话时,只需指定提供程序的标志和级别。 满足指定条件的任何调试打印语句都将输出到日志中。

使用 DoTraceMessage 语句

  1. DoTraceMessage 宏添加到代码中,就像调试打印例程一样。 DoTraceMessage 宏采用 3 个参数:标志级别 (TraceFlagName) ,用于定义写入跟踪消息时的条件、Message 字符串和可选变量列表。

    DoTraceMessage(TraceFlagName, Message, [VariableList... ]
    

    例如,以下 DoTraceMessage 语句在为跟踪会话启用 TRACE_DRIVER 标志(如 WPP_CONTROL_GUIDS 中定义)时写入包含 DoTraceMessage 语句的函数的名称。

         DoTraceMessage( TRACE_DRIVER, "\nEntering %!FUNC!" );
    
    

    该示例使用当前正在执行的函数的 预定义字符串 (%FUNC!) 。 有关 WPP 定义的格式规范字符串的详细信息,请参阅 什么是 WPP 扩展格式规范字符串?

  2. 若要生成跟踪消息,请使用 Logman 或 Tracelog 为跟踪提供程序创建跟踪会话,并指定一个跟踪标志,用于设置TRACE_DRIVER标志 (位 1,0x2) 。

//
//  DoTraceMessage examples
// 

     ...

// writes the name of the function that contains the trace statement when the flag, TRACE_DRIVER (bit 1, 0x2), 
// as defined in WPP_CONTROL_GUIDS, is enabled for the trace session.

     DoTraceMessage( TRACE_DRIVER, "\nEntering %!FUNC!" );

     ...

// writes the name of the function, the line number, and the error code 

      DoTraceMessage(
            TRACE_DRIVER,
            "[%s] Failed at %d (error code= %d)\n",
            __FUNCTION__,
            __LINE__,
            dwLastError);

如果在 Visual Studio 中使用 Windows 驱动程序模板,则会在 Trace.h 头文件中定义 TraceEvents 宏。

使用 TraceEvents 语句

  1. TraceEvents 宏添加到代码中,就像调试打印例程一样。 TraceEvents 宏采用以下参数:跟踪级别 (Level) 和跟踪标志 (Flags) ,用于定义写入跟踪消息时的条件、Message 字符串和可选变量列表。

    TraceEvents(Level, Flags, Message, [VariableList... ]
    

    例如,当满足跟踪级别和跟踪标志参数中指定的条件时,以下 TraceEvents 语句将写入包含 TraceEvents 语句的函数的名称。 跟踪级别是整数值;将跟踪位于或低于为该跟踪会话指定的跟踪级别的任何内容。 TRACE_LEVEL_INFORMATION在 Evntrace.h 中定义,其值为 4。 TRACE_DRIVER标志 (位 1,0x2) 在 WPP_CONTROL_GUIDS 中定义。 如果为跟踪会话设置了此TRACE_DRIVER位,并且跟踪级别为 4 或更高, 则 TraceEvents 将写入跟踪消息。

            TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
    
    

    该示例使用当前正在执行的函数的 预定义字符串 (%FUNC!) 。 有关 WPP 定义的格式规范字符串的详细信息,请参阅 什么是 WPP 扩展格式规范字符串?

  2. 若要生成跟踪消息,请使用 Logman 或 Tracelog 为跟踪提供程序创建跟踪会话。 将跟踪级别指定为 TRACE_LEVEL_INFORMATION (4) 或更高,并指定一个跟踪级别,用于设置TRACE_DRIVER位 (位 1,0x2) 。

//
//  TraceEvents examples
// 


    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");

//


    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,
                       "OSRUSBFX2 Driver Sample - Driver Framework Edition.\n");

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,
                "Built %s %s\n", __DATE__, __TIME__);

步骤 6:修改 Visual Studio 项目以运行 WPP 预处理器并生成解决方案

WDK 提供对 WPP 预处理器的支持,以便你可以使用 Visual Studio 和 MSBuild 环境运行预处理器。

运行 WPP 预处理器

  1. 选择并按住 (,或在“解决方案资源管理器”中右键单击) 驱动程序项目,然后选择“ 属性”。
  2. 在项目属性页中,选择“ 配置属性” ,然后选择“ WPP 跟踪”。
  3. “常规”下,将 “运行 WPP ”选项设置为 “是”。
  4. “命令行”下,添加任何其他选项以自定义跟踪行为。 有关可以添加的内容的信息,请参阅 WPP 预处理器
  5. 为目标配置和平台生成项目或解决方案。 请参阅 使用 WDK 生成驱动程序

有关生成过程的信息,请参阅 TraceWPP 任务WDK 和 Visual Studio 生成环境

还可以使用 TraceWPP 工具 (TraceWPP.exe) 运行独立于生成环境的预处理器。 此工具位于 WDK 的 bin/x86 和 bin/x64 子目录中。

步骤 7:启动跟踪会话以捕获和验证跟踪消息

若要验证是否已正确设置 WPP 跟踪,应在测试计算机上安装驱动程序或应用程序,然后创建跟踪会话来捕获跟踪消息。 可以使用任何跟踪控制器(例如 Logman、 TracelogTraceView)为跟踪提供程序创建跟踪会话。 可以将消息写入日志文件或发送到内核调试器。 根据所使用的跟踪消息函数,需要确保指定将生成消息的跟踪标志和跟踪级别。

例如,如果使用 Evntrace.h 中定义的跟踪级别,并且想要捕获TRACE_LEVEL_INFORMATION (4) 或更大,则需要将级别设置为 4。 将跟踪会话的级别设置为 4 时,还将捕获所有信息 (4) 、警告 (3) 、错误 (2) 以及关键 (1) 消息,前提是满足任何其他条件(例如跟踪标志)。

若要验证是否已生成所有消息,只需将跟踪级别和跟踪标志设置为最大值,以便生成所有消息。 跟踪标志使用 ULONG) (位掩码,因此可以设置所有位 (例如0xFFFFFFFF) 。 跟踪级别由字节值表示。 例如,如果使用 Logman,则可以指定覆盖所有级别的0xFF。

(使用 Logman 启动跟踪会话) 示例

logman create trace "myWPP_session" -p {11C3AAE4-0D88-41b3-43BD-AC38BF747E19} 0xffffffff 0xff -o c:\DriverTest\TraceFile.etl 

logman start "myWPP_session"

logman stop "myWPP_session"

(示例) 使用 TraceLog 启动跟踪会话

tracelog -start MyTrace -guid  MyProvider.guid -f d:\traces\testtrace.etl -flag 2 -level 0xFFFF

Tracelog 命令包含 -f 参数,用于指定事件跟踪日志文件的名称和位置。 它包括用于指定标志集的 -flag 参数和用于指定级别设置的 -level 参数。 可以省略这些参数,但某些跟踪提供程序不会生成任何跟踪消息,除非设置标志或级别。 跟踪级别在 Evntrace.h 文件中定义,跟踪级别提供了一种将跟踪消息分类为关键消息、错误消息、警告消息和信息性消息的便捷方法。