编译工具链

MSVC(Microsoft visual C++)和GCC都是编译器,(还有Clang)执行预处理-编译-汇编-链接这几个部分,不过每个部分所用工具各不相同。为了工具链是完整性以及一些运行时基本功能的保证,MSVC和GCC都带有一系列工具和库,这个构成完整的开发环境。

如果在代码中包含了#include <vcruntime.h>#include <msvcrt.h>,那么这个代码只能在 MSVC 环境中编译运行。

  • excpt.h:这是MSVC特有的异常处理头文件。说明代码依赖于MSVC的异常机制。
  • crtdefs.h:这是MSVC的C运行时库头文件,通常用于定义标准库函数的实现。如果包含了这些头文件,也意味着依赖于MSVC的标准库实现。

折中的存在是MinGW,主要作用是提供一个在Windows平台上使用GCC编译器的环境。它提供的头文件和库可以GCC编译通过。

ETW编写事件4种方式

清单

基于这种方式的实现还需要配置文件。而这个配置文件是Windows SDK中的mc.exe 处理的。但是要注意对应的mc版本。

<?xml version="1.0" encoding="UTF-16"?>
<instrumentationManifest xmlns="http://schemas.microsoft.com/win/2004/08/events"
                         xmlns:win="https://manifests.microsoft.com/win/2004/08/windows/events"
                         xmlns:xs="https://www.w3.org/2001/XMLSchema">

    <instrumentation>
        <events>

            <!-- 事件提供程序 -->
            <provider name="MyCustomProvider" 
                      guid="{78a1b3de-42A7-4111-85B2-8D198012EDDF}"  
                      symbol="ProviderGuid"
                      resourceFileName="c:\Users\Administrator\Desktop\ioplus\self.exe" 
                      messageFileName="c:\Users\Administrator\Desktop\ioplus\self.exe" 
                      message="$(string.Provider.Name)">
                
                <!-- 定义事件的关键字和其他映射(如果有) -->
                <keywords>
                    <keyword name="General" symbol="GENERAL_KEYWORD" mask="0x1"/>
                </keywords>

                <!-- 定义事件模板 -->
                <templates>
                    <template tid="MyEventTemplate">
                        <!-- 事件数据字段 -->
                        <data name="Message" inType="win:UnicodeString"/>
                        <data name="AnotherMessage" inType="win:UnicodeString"/>
                        <data name="Value" inType="win:UInt32"/>
                    </template>
                </templates>

                <!-- 事件定义 -->
                <events>
                    <event value="1"
                           level="win:Informational"
                           template="MyEventTemplate"
                           symbol="MyEvent"
                           message="$(string.Event.Message)"
                           keywords="General" />
                </events>
            </provider>

        </events>
    </instrumentation>

    <!-- 本地化资源 -->
    <localization>
        <resources culture="en-US">
            <stringTable>
                <string id="Provider.Name" value="My Custom ETW Provider"/>
                <string id="Event.Message" value="This is a custom ETW event."/>
            </stringTable>
        </resources>
    </localization>

</instrumentationManifest>

清单对应的程序

使用Windows evntprov中的宏:

  • 清单对应的程序模板Writing Manifest-based Events - Win32 apps | Microsoft Learn
    #include <windows.h>
    #include <evntprov.h>
    
    GUID ProviderGuid = { 0x78a1b3de, 0x42a7, 0x4111, {  0x85, 0xb2, 0x8d, 0x19, 0x98, 0x12, 0xed, 0xdf } };  
    /* 定义唯一的 GUID */
    // 3970F9cf-2c0c-4f11-b1cc-e3a1e9958833
    REGHANDLE RegHandle;
    
    void WriteEvent()
    {
        // 注册提供程序
        ULONG status = EventRegister(&ProviderGuid, NULL, NULL, &RegHandle);
    
        // 写入一个简单事件
        EVENT_DESCRIPTOR descriptor = {};
        descriptor.Id = 1;
        descriptor.Version = 0;
        descriptor.Channel = 0;
        descriptor.Level = 4; // 信息级别
        descriptor.Keyword = 0;
    
        EVENT_DATA_DESCRIPTOR dataDesc;
        EventDataDescCreate(&dataDesc, "Hello, ETW!", strlen("Hello, ETW!"));
    
        ULONG status2 = EventWrite(RegHandle, &descriptor, 1, &dataDesc);
    
        // 注销提供程序
        EventUnregister(RegHandle);
    }
    
    int main()
    {
        WriteEvent();
        return 0;
    }

TraceLogging

  • TraceLogging 提供程序,封装的接口:
    #include <windows.h> // or <wdm.h> for kernel-mode.
    #include <winmeta.h> // For event level definitions.
    #include <TraceLoggingProvider.h> // 包含这个头文件
    
    TRACELOGGING_DEFINE_PROVIDER( // 用这个宏生成全局的句柄,这个句柄用于和ETW连接
        g_hProvider, // 生产者句柄的名字
        "MyCompany.MyComponent", // 取一个人可以读的名字给生产者
        // {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); // 注册刚刚的句柄, 打开组件与 ETW 的连接。
    
        TraceLoggingWrite( // 生成 TraceLogging 编码的 ETW 事件。
            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); // 关闭组件与 ETW 的连接
        return 0;
    }
  • Windows SDK 中的 TraceLoggingProvider.h 头文件支持使用 C 或 C++ 内核和用户模式代码生成 TraceLogging 编码事件。
  • EventSource 类支持生成 TraceLogging 编码的事件(使用 Write 方法或使用 EtwSelfDescribingEventFormat 标志构建时)。
  • LoggingChannel Windows Runtime 类支持生成 TraceLogging 编码的事件。
    但是MinGW没有这个头文件,虽然接口简单却只能使用MSVC编译。

    WPP 事件

WDK 提供对 WPP 预处理器的支持,以便使用 Visual Studio 和 MSBuild 环境运行预处理器。还可以使用 TraceWPP 工具 (TraceWPP.exe,MinGW中没有这个工具) 运行独立于生成环境的预处理器。 此工具位于 WDK 的 bin/x86 和 bin/x64 子目录中。具体预处理需求

MOF事件

也是需要MOF 编译器 (Mofcomp.exe)

ETW 架构

ETW的架构:

所有事件跟踪的头文件事件跟踪 - Win32 apps | Microsoft Learn

事件跟踪原理关于事件跟踪 - Win32 apps | Microsoft Learn


文章作者: 易百分
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 易百分 !
  目录