TRACELOGGING_DEFINE_PROVIDER宏 (traceloggingprovider.h)

定义 TraceLogging 提供程序的句柄。

语法

void TRACELOGGING_DEFINE_PROVIDER(
  [in]            handleVariable,
  [in]            providerName,
  [in]            providerId,
  [in, optional]  __VA_ARGS__
);

参数

[in] handleVariable

要用于提供程序句柄的名称,使用组件对全局变量的命名约定,例如 MyComponentLogg_hMyProvider

[in] providerName

具有 TraceLogging 提供程序名称的字符串文本。 此名称应特定于组织和组件,以便它不会与其他组件的提供程序冲突。 此名称字符串将包含在提供程序生成的每个 ETW 事件中,因此请尝试使用相对较短的名称。 例如,可以使用 或 "MyCompany.MyOrganization.MyComponent""MyCompany.MyComponent"名称。

这必须是字符串文本。 请勿使用变量。

[in] providerId

提供程序的 ETW 控件 GUID,指定为逗号分隔列表(括号中包含 11 个整数)。 例如,GUID {ce5fa4ea-ab00-5402-8b76-9f76ac858fb5} 将表示为 (0xce5fa4ea,0xab00,0x5402,0x8b,0x76,0x9f,0x76,0xac,0x85,0x8f,0xb5)

尽管任何唯一 GUID 都可用于提供程序 ID,但 Microsoft 建议使用使用 ETW 名称哈希算法从提供程序名称生成的 GUID。 有关生成提供程序 ID 的信息,请参阅下文。

[in, optional] __VA_ARGS__

提供程序的可选参数。 大多数提供程序不需要指定任何可选参数。

如果希望提供程序与 ETW 提供程序组相关联,请添加 TraceLoggingOptionGroup 宏以指定提供程序的组 GUID。 否则,请勿指定任何 __VA_ARGS__ 参数。

返回值

备注

TraceLogging 提供程序是可将事件发送到 ETW 的连接。 宏 TRACELOGGING_DEFINE_PROVIDER 定义 TraceLogging 提供程序,并创建可用于访问它的句柄。 它还记录提供程序信息,例如提供程序的名称和 GUID。

应在 .c 或 .cpp 文件中调用此宏,以定义 TraceLogging 提供程序的句柄。 例如,如果我的提供程序命名 MyCompany.MyComponent 为 ,并且控件 GUID 为 {ce5fa4ea-ab00-5402-8b76-9f76ac858fb5} ,则我会通过将以下代码添加到组件中的 .c 或 .cpp 文件之一来定义提供程序:

TRACELOGGING_DEFINE_PROVIDER( // defines g_hProvider
    g_hProvider, // Name of the provider handle
    "MyCompany.MyComponent", // Human-readable name for the provider
    // {ce5fa4ea-ab00-5402-8b76-9f76ac858fb5}
    (0xce5fa4ea,0xab00,0x5402,0x8b,0x76,0x9f,0x76,0xac,0x85,0x8f,0xb5));

可以将上述 TRACELOGGING_DEFINE_PROVIDER 宏视为定义 g_hMyProvider 提供程序句柄常量,类似于以下代码:

const TraceLoggingHProvider g_hMyProvider = ...;

生成的句柄具有模块范围,可以在定义它的 EXE、DLL 或 SYS 模块中的任何位置使用。 根据需要使用 TRACELOGGING_DECLARE_PROVIDER 宏 (例如在标头) 中转发声明句柄,以便它可供组件中的其他 .c 或.cpp文件使用。

组件开始运行时,提供程序将处于未注册状态。 将无提示地忽略使用它生成事件的任何尝试。 需要先使用 TraceLoggingRegister 注册提供程序,然后才能响应任何写入调用。 这通常在组件启动期间完成,例如在 、wmain、、 WinMainDllMain(DLL_PROCESS_ATTACH)DriverEntrymain。 在组件关闭时,通过调用 TraceLoggingUnregister 来注销提供程序。

注意

定义的 TRACELOGGING_DEFINE_PROVIDER 提供程序句柄的范围限定为模块。 可以根据需要在 EXE、DLL 或 SYS 文件中使用该句柄,但不应在模块范围之外使用,即不应将其传递给同一进程中的其他 DLL。 每个 EXE、DLL 或 SYS 文件都应使用其自己的提供程序句柄,并应执行自己的注册和注销。 在调试版本中,如果尝试使用来自另一个模块的提供程序句柄进行写入,则会触发断言。

提供程序名称和 ID

ETW 使用提供程序 ID (也称为提供程序 GUID 或控制 GUID) 来执行事件筛选和路由。 例如,如果具有名为 MyCompany.MyComponent 的提供程序 ID {ce5fa4ea-ab00-5402-8b76-9f76ac858fb5} ,则可以启动跟踪,以使用跟踪 日志 命令(如 tracelog -start MySessionName -f MySession.etl -guid #ce5fa4ea-ab00-5402-8b76-9f76ac858fb5)从此提供程序捕获事件。

所有 ETW 提供程序都由提供程序名称和提供程序 ID 标识。 名称和 ID 都需要是唯一的,这样它们就不会与其他提供程序冲突。 此外,应链接名称和 ID:将特定名称与 ETW 提供程序的特定 ID 一起使用后,该名称不应与任何其他 ID 一起使用,并且该 ID 不应与任何其他名称一起使用。

提供程序 ID 可以是任何唯一 GUID,例如使用 guidgen SDK 工具或 https://uuidgen.org生成的 GUID。但是,Microsoft 建议使用下面所述的 ETW 名称哈希算法从提供程序名称生成提供程序 ID,而不是为提供程序 ID 使用随机生成的 GUID。 这提供了几个好处:更容易记住名称;ID 和名称会自动链接;tracelog、traceview、EventSource 和 WPR 等工具对使用此算法生成的 ID 的提供程序提供特殊支持。

例如,如果具有名为 MyCompany.MyComponent 的提供程序 ID {ce5fa4ea-ab00-5402-8b76-9f76ac858fb5} ,则可以启动跟踪,以使用跟踪 日志 命令(如 tracelog -start MySessionName -f MySession.etl -guid *MyCompany.MyComponent)从此提供程序捕获事件。 这之所以有效,是因为提供程序 ID {ce5fa4ea-ab00-5402-8b76-9f76ac858fb5} 是通过对提供程序名称 MyCompany.MyComponent进行哈希生成的,因此 tracefmt 工具认为 -guid *MyCompany.MyComponent 等效于 -guid #ce5fa4ea-ab00-5402-8b76-9f76ac858fb5

可以使用 PowerShell 通过 EventSource 类使用 ETW 名称哈希算法获取特定提供程序名称的提供程序 ID:

[System.Diagnostics.Tracing.EventSource]::new("MyCompany.MyComponent").Guid

结果:

Guid
----
ce5fa4ea-ab00-5402-8b76-9f76ac858fb5

在 C# 中,可以按如下所示实现 ETW 名称哈希算法:

static Guid ProviderIdFromName(string name)
{
    var signature = new byte[] {
        0x48, 0x2C, 0x2D, 0xB2, 0xC3, 0x90, 0x47, 0xC8,
        0x87, 0xF8, 0x1A, 0x15, 0xBF, 0xC1, 0x30, 0xFB };
    var nameBytes = System.Text.Encoding.BigEndianUnicode.GetBytes(name.ToUpperInvariant());
    using (var sha1 = new System.Security.Cryptography.SHA1Managed())
    {
        sha1.TransformBlock(signature, 0, signature.Length, null, 0);
        sha1.TransformFinalBlock(nameBytes, 0, nameBytes.Length);
        var hash = sha1.Hash;
        Array.Resize(ref hash, 16);
        hash[7] = (byte)((hash[7] & 0x0F) | 0x50);
        return new Guid(hash);
    }
}

示例

#include <windows.h> // or <wdm.h> for kernel-mode.
#include <winmeta.h> // For event level definitions.
#include <TraceLoggingProvider.h>

TRACELOGGING_DEFINE_PROVIDER( // defines g_hProvider
    g_hProvider, // Name of the provider handle
    "MyCompany.MyComponent", // Human-readable name for the provider
    // {ce5fa4ea-ab00-5402-8b76-9f76ac858fb5}
    (0xce5fa4ea,0xab00,0x5402,0x8b,0x76,0x9f,0x76,0xac,0x85,0x8f,0xb5));

int main(int argc, char* argv[]) // or DriverEntry for kernel-mode.
{
    TraceLoggingRegister(g_hProvider);

    TraceLoggingWrite(
        g_hProvider,
        "MyEvent1",
        TraceLoggingLevel(WINEVENT_LEVEL_WARNING), // Levels defined in <winmeta.h>
        TraceLoggingKeyword(MyEventCategories), // Provider-defined categories
        TraceLoggingString(argv[0], "arg0"), // field name is "arg0"
        TraceLoggingInt32(argc)); // field name is implicitly "argc"

    TraceLoggingUnregister(g_hProvider);
    return 0;
}

要求

要求
最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用]
最低受支持的服务器 Windows Server 2008 [桌面应用 | UWP 应用]
目标平台 Windows
标头 traceloggingprovider.h

另请参阅

TRACELOGGING_DECLARE_PROVIDER

TraceLoggingWrite