Intenté replicar el breve programa de muestra para TraceLogging que proporciona Microsoft (ver más abajo, con cambios menores). Completé el "desarrollo" (en lugar de copiar) en Visual Studio 2019. Todo está bien, se compila sin problemas, se ejecuta sin problemas, pero en ninguna parte de mi PC puedo encontrar un archivo * .etl o * .log actualizado, ni lo encuentro una entrada en algún lugar del Visor de eventos.

Leí atentamente la documentación de Microsoft y busqué en Internet durante muchas horas, pero no encontré hallazgos útiles.

Sé que soy estúpido de vez en cuando y debo perderme algo obvio, pero ¿qué es? ¿Alguna pista, por favor? ¡Muchas gracias!

#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;
}
1
Primicerius Aedifex 13 ago. 2020 a las 16:36

2 respuestas

La mejor respuesta

En primer lugar, ejecutar este código C ++ no generará el archivo .log o .etl que desea, solo envía el evento TraceLogging, debe capturarlo de otras formas para generar el archivo etl.

De acuerdo con MSDN, tiene dos pasos para capturar eventos de TraceLogging:

  1. Capture datos de seguimiento con WPR
  2. Capture eventos de TraceLogging en Windows Phone

Primero cree un archivo .WPRP, utilicé el mismo código C ++ y el archivo WPRP de MSDN de la siguiente manera.

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

Archivo WPRP de muestra

<?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>

Luego, inicie la captura utilizando WPR desde una ventana de símbolo del sistema elevada (ejecutar como administrador).

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

A continuación, puede ejecutar la aplicación que contiene sus eventos y detener la captura de seguimiento.

wpr.exe -stop C: \ Users \ songz \ Desktop \ test.etl descripción

Esto puede generar el archivo etl que necesita normalmente.

enter image description here

Después de completar las operaciones anteriores, debe capturar los eventos de TraceLogging. De acuerdo con github, puede usar lo siguiente comandos:

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

xperf -stop MySession

Nota: debería utilizar como xperf -start MySession -f MyFile.etl -on Id

Finalmente puedes visualizar la información correspondiente a través de WPA.

enter image description here

0
Zhu Song 14 ago. 2020 a las 07:36

Zhu Song, ¡muchas gracias por tu aporte! Tus comentarios me llevaron al camino correcto. Bueno, no seguí estrictamente tu texto, pero encontré cosas nuevas para leer.

Quiero que el controlador también sea parte de mi aplicación. Entonces, lo que hice fue aproximadamente lo siguiente:

  • Preparar la estructura EVENT_TRACE_PROPERTIES
  • TraceLogRegister
  • StartTrace
  • EnableTraceEx2 (habilitar)
  • TraceLoggingWrite
  • TraceLoggingUnregister
  • EnableTraceEx2 (deshabilitar)
  • ControlTrace (detener)

Esto resultó en un archivo xxx.etl que pude ver con tracerpt o WPA.

¡Gracias de nuevo! Estoy bien ahora.

Este es el código en detalle:

#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;
}
0
Primicerius Aedifex 15 ago. 2020 a las 19:52