简体   繁体   English

找不到 output 的 Win32 TraceLogging

[英]Cannot find output of Win32 TraceLogging

I tried to replicate the short sample program for TraceLogging that Microsoft provides (see below, with minor changes).我试图复制 Microsoft 提供的用于 TraceLogging 的简短示例程序(见下文,稍作改动)。 I completed the "development" (rather copy) in Visual Studio 2019. All is fine, compiles without issues, runs without issues, but nowhere on my PC I can find an updated *.etl or *.log file, nor do I find an entry somewhere in the Event Viewer.我在 Visual Studio 2019 中完成了“开发”(而不是复制)。一切都很好,编译没有问题,运行没有问题,但在我的电脑上找不到更新的 *.etl 或 *.log 文件,我也找不到事件查看器中某处的条目。

I carefully read the Microsoft documentation and I searched the Inte.net for many hours, but no useful findings.我仔细阅读了 Microsoft 文档并在 Inte.net 上搜索了很多小时,但没有找到有用的结果。

I know that I'm stupid from time to time and I must miss something obvious, but what is it?我知道我有时很愚蠢,我一定会错过一些明显的东西,但那是什么? Any hints, please?有什么提示吗? Many thanks!非常感谢!

#include <windows.h> // or <wdm.h> for kernel-mode.
#include <winmeta.h>
#include <TraceLoggingProvider.h>
#include <stdio.h>

// Define the GUID to use in TraceLoggingRegister 
// {5B5852D4-DC24-4A0F-87B6-9115AE9D2768}
TRACELOGGING_DEFINE_PROVIDER (      // defines g_hProvider
    g_hProvider,                    // Name of the provider variable
    "Test-Test",                    // Human-readable name of the provider
    (0x5b5852d4, 0xdc24, 0x4a0f, 0x87, 0xb6, 0x91, 0x15, 0xae, 0x9d, 0x27, 0x68) );     // Provider GUID


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

    hrRegister = TraceLoggingRegister ( g_hProvider );
    if ( !SUCCEEDED ( hrRegister ) ) {
        printf ( "TraceLoggingRegister failed. Stopping." );
        return 1;
    }
    TraceLoggingWrite (
        g_hProvider,
        "MyEvent1",
        // TraceLoggingChannel ( WINEVENT_CHANNEL_CLASSIC_TRACE ),
        // TraceLoggingLevel ( WINEVENT_LEVEL_CRITICAL ),
        TraceLoggingString ( argv[0], "arg0" ),     // field name is "arg0"
        TraceLoggingInt32 ( argc ) );               // field name is implicitly "argc"

    TraceLoggingUnregister ( g_hProvider );
    return 0;
}

First of all, running this C++ code will not generate the.log or.etl file you want, it just sends the TraceLogging event, you need to capture it in other ways to generate the etl file.首先,运行这个C++代码不会生成你想要的.log或者.etl文件,它只是发送TraceLogging事件,你需要通过其他方式捕获它来生成etl文件。

According to the MSDN ,You have two steps to capture TraceLogging events:根据MSDN ,您有两个步骤来捕获 TraceLogging 事件:

  1. Capture trace data with WPR使用 WPR 捕获跟踪数据
  2. Capture TraceLogging events on Windows Phone在 Windows 电话上捕获 TraceLogging 事件

First create a.WPRP file, I used the same C++ code and WPRP file from MSDN as follow.首先创建一个 .WPRP 文件,我使用了相同的 C++ 代码和来自 MSDN 的 WPRP 文件,如下所示。

test.cpp测试.cpp

#include <windows.h> // or <wdm.h> for kernel-mode.
#include <winmeta.h>
#include <TraceLoggingProvider.h>
#include <stdio.h>


    // Define the GUID to use in TraceLoggingProviderRegister 
    // {3970F9cf-2c0c-4f11-b1cc-e3a1e9958833}
TRACELOGGING_DEFINE_PROVIDER(
    g_hMyComponentProvider,
    "SimpleTraceLoggingProvider",
    (0x3970f9cf, 0x2c0c, 0x4f11, 0xb1, 0xcc, 0xe3, 0xa1, 0xe9, 0x95, 0x88, 0x33));


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);
}

Sample WPRP file示例 WPRP 文件

<?xml version="1.0" encoding="utf-8"?>
<!-- TODO: 
1. Find and replace "SimpleTraceLoggingProvider" with the name of your provider.
2. See TODO below to update GUID for your event provider
-->
<WindowsPerformanceRecorder Version="1.0" Author="Microsoft Corporation" Copyright="Microsoft Corporation" Company="Microsoft Corporation">
  <Profiles>
    <EventCollector Id="EventCollector_SimpleTraceLoggingProvider" Name="SimpleTraceLoggingProvider">
      <BufferSize Value="64" />
      <Buffers Value="4" />
    </EventCollector>

    <!-- TODO: 
 1. Update Name attribute in EventProvider xml element with your provider GUID, eg: Name="3970F9cf-2c0c-4f11-b1cc-e3a1e9958833". Or
    if you specify an EventSource C# provider or call TraceLoggingRegister(...) without a GUID, use star (*) before your provider
    name, eg: Name="*MyEventSourceProvider" which will enable your provider appropriately.  
 2. This sample lists one EventProvider xml element and references it in a Profile with EventProviderId xml element. 
    For your component wprp, enable the required number of providers and fix the Profile xml element appropriately
-->
    <EventProvider Id="EventProvider_SimpleTraceLoggingProvider" Name="*SimpleTraceLoggingProvider" />

    <Profile Id="SimpleTraceLoggingProvider.Verbose.File" Name="SimpleTraceLoggingProvider" Description="SimpleTraceLoggingProvider" LoggingMode="File" DetailLevel="Verbose">
      <Collectors>
        <EventCollectorId Value="EventCollector_SimpleTraceLoggingProvider">
          <EventProviders>
            <!-- TODO:
 1. Fix your EventProviderId with Value same as the Id attribute on EventProvider xml element above
-->
            <EventProviderId Value="EventProvider_SimpleTraceLoggingProvider" />
          </EventProviders>
        </EventCollectorId>
      </Collectors>
    </Profile>

    <Profile Id="SimpleTraceLoggingProvider.Light.File" Name="SimpleTraceLoggingProvider" Description="SimpleTraceLoggingProvider" Base="SimpleTraceLoggingProvider.Verbose.File" LoggingMode="File" DetailLevel="Light" />
    <Profile Id="SimpleTraceLoggingProvider.Verbose.Memory" Name="SimpleTraceLoggingProvider" Description="SimpleTraceLoggingProvider" Base="SimpleTraceLoggingProvider.Verbose.File" LoggingMode="Memory" DetailLevel="Verbose" />
    <Profile Id="SimpleTraceLoggingProvider.Light.Memory" Name="SimpleTraceLoggingProvider" Description="SimpleTraceLoggingProvider" Base="SimpleTraceLoggingProvider.Verbose.File" LoggingMode="Memory" DetailLevel="Light" />

  </Profiles>
</WindowsPerformanceRecorder>

Then start the capture using WPR from an elevated (run as Administrator) Command Prompt window.然后使用 WPR 从提升的(以管理员身份运行)命令提示符 window 开始捕获。

wpr.exe -start C:\Users\songz\Desktop\test.wprp wpr.exe -start C:\Users\songz\Desktop\test.wprp

Next you may run the application that contains your events and stop the trace capture.接下来,您可以运行包含您的事件的应用程序并停止跟踪捕获。

wpr.exe -stop C:\Users\songz\Desktop\test.etl description wpr.exe -stop C:\Users\songz\Desktop\test.etl 描述

This can generate the etl file you need normally.这样就可以生成你正常需要的etl文件了。

在此处输入图像描述

After completing the above operations, you should capture TraceLogging events.完成上述操作后,您应该捕获 TraceLogging 事件。 According to the github , you can use the following commands:根据github ,可以使用以下命令:

xperf -start MySession -f C:\Users\songz\Desktop\test.etl -on 3970F9cf-2c0c-4f11-b1cc-e3a1e9958833 xperf -start MySession -f C:\Users\songz\Desktop\test.etl -on 3970F9cf-2c0c-4f11-b1cc-e3a1e9958833

xperf -stop MySession xperf -stop MySession

Note:You should use like xperf -start MySession -f MyFile.etl -on Id注意:您应该使用xperf -start MySession -f MyFile.etl -on Id

Finally you can view the corresponding information through WPA.最后可以通过WPA查看相应的信息。

在此处输入图像描述

Zhu Song, thank you very much for your input.朱松,非常感谢您的意见。 Your comments brought me to the right track, Well, I did not follow strictly your text.你的评论把我带到了正确的轨道上,好吧,我没有严格按照你的文字。 but I found new stuff to read.但我发现了新的东西要读。

I want the controller to be part of my application as well.我希望 controller 也成为我的应用程序的一部分。 So, what I did is roughly the following:所以,我所做的大致如下:

  • Prepare EVENT_TRACE_PROPERTIES structure准备 EVENT_TRACE_PROPERTIES 结构
  • TraceLogRegister TraceLogRegister
  • StartTrace开始追踪
  • EnableTraceEx2 (enable) EnableTraceEx2(启用)
  • TraceLoggingWrite TraceLoggingWrite
  • TraceLoggingUnregister TraceLogging注销
  • EnableTraceEx2 (disable) EnableTraceEx2(禁用)
  • ControlTrace (stop)控制跟踪(停止)

This resulted in an xxx.etl file that I could view with tracerpt or WPA.这产生了一个 xxx.etl 文件,我可以使用 tracerpt 或 WPA 查看该文件。

Thanks again.再次感谢。 I'm all fine now.我现在一切都好。

This is the code in detail:这是详细的代码:

#include <windows.h> // or <wdm.h> for kernel-mode.
#include <winmeta.h>
#include <TraceLoggingProvider.h>
#include <evntrace.h>
#include <stdio.h>
#include <strsafe.h>

#define LOGFILE_NAME TEXT(".\\Test-Test.etl")
#define LOGSESSION_NAME TEXT("Test-Test-Session")


// Define the GUID to use in TraceLoggingRegister 
// {5B5852D4-DC24-4A0F-87B6-9115AE9D2768}
TRACELOGGING_DEFINE_PROVIDER (      // defines g_hProvider
    g_hProvider,                    // Name of the provider variable
    "Test-Test",                    // Human-readable name of the provider
    (0x5b5852d4, 0xdc24, 0x4a0f, 0x87, 0xb6, 0x91, 0x15, 0xae, 0x9d, 0x27, 0x68) );     // Provider GUID

static const GUID ProviderGUID = { 0x5b5852d4, 0xdc24, 0x4a0f, {0x87, 0xb6, 0x91, 0x15, 0xae, 0x9d, 0x27, 0x68} };


int main ( int argc, char *argv[] ) // or DriverEntry for kernel-mode.
{
    TRACEHANDLE hTrace = 0;
    EVENT_TRACE_PROPERTIES *petProperties;
    HRESULT hrRegister;

    ULONG bufferSize, ret_val;

    bufferSize = sizeof ( EVENT_TRACE_PROPERTIES ) + sizeof ( LOGFILE_NAME ) + sizeof ( LOGSESSION_NAME ) + 512;    // The additional bytes are necessary because the path of thr LOGFILE_NAME is expanded
    petProperties = (EVENT_TRACE_PROPERTIES *) malloc ( bufferSize );
    if ( petProperties == NULL ) {
        printf ( "Unable to allocate %d bytes for properties structure.\n", bufferSize );
        return 1;
    }

    ZeroMemory ( petProperties, bufferSize );
    petProperties->Wnode.BufferSize = bufferSize;
    petProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
    petProperties->Wnode.ClientContext = 1;
    petProperties->Wnode.Guid = ProviderGUID;
    petProperties->LogFileMode = EVENT_TRACE_FILE_MODE_SEQUENTIAL | EVENT_TRACE_PRIVATE_LOGGER_MODE | EVENT_TRACE_PRIVATE_IN_PROC;
    petProperties->MaximumFileSize = 100;       // was 1
    petProperties->BufferSize = 512;
    petProperties->MinimumBuffers = 8;
    petProperties->MaximumBuffers = 64;
    petProperties->LoggerNameOffset = sizeof ( EVENT_TRACE_PROPERTIES );
    petProperties->LogFileNameOffset = sizeof ( EVENT_TRACE_PROPERTIES ) + sizeof ( LOGSESSION_NAME );
    StringCbCopy ( (LPWSTR) ((char *) petProperties + petProperties->LogFileNameOffset), sizeof ( LOGFILE_NAME ), LOGFILE_NAME );

    hrRegister = TraceLoggingRegister ( g_hProvider );
    if ( !SUCCEEDED ( hrRegister ) ) {
        printf ( "TraceLoggingRegister failed. Stopping.\n" );
        return 1;
    }

    ret_val = StartTrace ( &hTrace, LOGSESSION_NAME, petProperties );
    if ( ret_val != ERROR_SUCCESS ) {
        printf ( "StartTrace failed with %i\n", ret_val );
        if ( ret_val != ERROR_ALREADY_EXISTS )
            return 1;
    }

    ret_val = EnableTraceEx2 ( hTrace, &ProviderGUID, EVENT_CONTROL_CODE_ENABLE_PROVIDER, TRACE_LEVEL_VERBOSE, 0, 0, 0, NULL );
    if ( ret_val != ERROR_SUCCESS ) {
        printf ( "EnableTraceEx2(enable) failed with %i\n", ret_val );
        ret_val = ControlTrace ( hTrace, LOGSESSION_NAME, petProperties, EVENT_TRACE_CONTROL_STOP );
        if ( ret_val != ERROR_SUCCESS ) {
            printf ( "ControlTrace(stop) failed with %i\n", ret_val );
        }
        return 1;
    }

    if ( TraceLoggingProviderEnabled ( g_hProvider, 0, 0 ) )
        printf ( "TraceLoggingProvider enabled\n" );
    else
        printf ( "TraceLoggingProvider NOT enabled\n" );

    TraceLoggingWrite (
        g_hProvider,
        "MyEvent1",
        TraceLoggingString ( argv[0], "arg0" ),     // field name is "arg0"
        TraceLoggingInt32 ( argc ) );               // field name is implicitly "argc"

    TraceLoggingUnregister ( g_hProvider );

    ret_val = EnableTraceEx2 ( hTrace, &ProviderGUID, EVENT_CONTROL_CODE_DISABLE_PROVIDER, TRACE_LEVEL_VERBOSE, 0, 0, 0, NULL );
    if ( ret_val != ERROR_SUCCESS ) {
        printf ( "EnableTraceEx2(disable) failed with %i\n", ret_val );
    }
    ret_val = ControlTrace ( hTrace, LOGSESSION_NAME, petProperties, EVENT_TRACE_CONTROL_STOP );
    if ( ret_val != ERROR_SUCCESS ) {
        printf ( "ControlTrace(stop) failed with %i\n", ret_val );
    }

    return 0;
}

ETW is an event routing system. ETW 是一个事件路由系统。 TraceLoggingWrite means "send the event to ETW". TraceLoggingWrite 表示“将事件发送到 ETW”。 But if nobody is interested in your event then ETW will just ignore it.但是,如果没有人对您的活动感兴趣,那么 ETW 将忽略它。

To collect the data from TraceLoggingWrite, there needs to be an ETW session that is listening for events from you.要从 TraceLoggingWrite 收集数据,需要有一个正在侦听您的事件的 ETW session。 There are many ways to start and control ETW sessions, including the StartTrace API, the AutoLogger registry key, the WPR tool, and the TRACELOG tool.启动和控制 ETW 会话的方法有很多,包括 StartTrace API、AutoLogger 注册表项、WPR 工具和 TRACELOG 工具。

I usually prefer the TRACELOG tool.我通常更喜欢 TRACELOG 工具。 It is included with the Windows SDK, so it is installed if I have installed Visual Studio, and it will be on my path if I open a "Developer command prompt".它包含在 Windows SDK 中,因此如果我安装了 Visual Studio,它就会安装,如果我打开“开发人员命令提示符”,它就会在我的路径上。 On my computer, TRACELOG is in C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x86\tracelog.exe .在我的电脑上,TRACELOG 位于C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x86\tracelog.exe中。

To capture events from the provider you show in your source code, I would run:要从您在源代码中显示的提供程序捕获事件,我将运行:

TRACELOG -start MySessionName -f MySession.etl -guid #5B5852D4-DC24-4A0F-87B6-9115AE9D2768

After my code has run, I would stop the trace with:在我的代码运行后,我将停止跟踪:

TRACELOG -stop MySessionName

I could then use various tools to decode the trace.然后我可以使用各种工具来解码跟踪。 I usually use the TRACEFMT tool.我通常使用 TRACEFMT 工具。

TRACEFMT MySession.etl

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM