Avvio rapido di TraceLogging C/C++

La sezione seguente descrive i passaggi di base necessari per aggiungere TraceLogging al codice in modalità utente C/C++.

Prerequisiti

  • Microsoft Visual Studio 2013 o versione successiva.
  • Windows 10 Software Development Kit (SDK) è necessario per scrivere un provider in modalità utente.
  • Windows Driver Kit (WDK) per Windows 10 è necessario per scrivere un provider in modalità kernel.

Importante

Per evitare errori del linker per le funzioni , EventWriteTransfero EventUnregister non EventRegisterrisolte, collegarsi a advapi32.lib durante la compilazione di questi esempi.

Per raccogliere e decodificare gli eventi da questi esempi, è necessario avviare una traccia usando uno strumento come tracelog o traceview, eseguire l'esempio, arrestare la traccia usando uno strumento come tracelog o traceview e decodificare la traccia usando uno strumento di decodifica come tracefmt o traceview. Ad esempio, se il provider è stato definito tramite GUID {0205c616-cf97-5c11-9756-56a2cee02ca7}, è possibile visualizzare gli eventi di questi esempi usando il log di traccia degli strumenti di Windows SDK e tracefmt come indicato di seguito:

  • tracelog -start MyTraceSession -f MyTraceFile.etl -guid #0205c616-cf97-5c11-9756-56a2cee02ca7
  • Eseguire l'esempio.
  • tracelog -stop MyTraceSession
  • tracefmt -o MyTraceFile.txt MyTraceFile.etl
  • notepad MyTraceFile.txt

SimpleTraceLoggingExample.h

Questa intestazione di esempio include le API TraceLogging e inoltra dichiara l'handle del provider che verrà usato per registrare gli eventi. Qualsiasi classe che vuole usare TraceLogging includerà questa intestazione e potrà quindi avviare la registrazione.

#pragma once

#include <windows.h> // Definitions required by TraceLoggingProvider.h
#include <TraceLoggingProvider.h> // The C/C++ TraceLogging API

// Forward-declare the g_hMyComponentProvider variable that you will use for tracing in this component
TRACELOGGING_DECLARE_PROVIDER(g_hMyComponentProvider);

Il file di intestazione include TraceLoggingProvider.h che definisce l'API TraceLogging C/C++. È necessario includere windows.h prima perché definisce le costanti utilizzate da TraceLoggingProvider.h.

Il file di intestazione inoltra dichiara l'handle g_hMyComponentProvider del provider che verrà passato alle API TraceLogging per registrare gli eventi. Questo handle deve essere accessibile a qualsiasi codice che desidera utilizzare TraceLogging.

TRACELOGGING_DECLARE_PROVIDER è una macro che crea un extern const TraceLoggingHProvider handle usando il nome specificato, che nell'esempio precedente è g_hMyComponentProvider. La variabile di gestione del provider effettiva verrà allocata in un file di codice.

SimpleTraceLoggingExample.cpp

L'esempio seguente registra il provider, registra un evento e annulla la registrazione del provider.

#include "SimpleTraceLoggingExample.h"

// Define a handle to a TraceLogging provider
TRACELOGGING_DEFINE_PROVIDER(
    g_hMyComponentProvider,
    "SimpleTraceLoggingProvider",
    // {0205c616-cf97-5c11-9756-56a2cee02ca7}
    (0x0205c616,0xcf97,0x5c11,0x97,0x56,0x56,0xa2,0xce,0xe0,0x2c,0xa7));

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

L'esempio precedente include SimpleTraceLoggingExample.h che contiene la variabile del provider globale che verrà usata dal codice per registrare gli eventi.

La macro TRACELOGGING_DEFINE_PROVIDER alloca l'archiviazione e definisce la variabile di handle del provider. Il nome della variabile specificato per questa macro deve corrispondere al nome usato nella macro TRACELOGGING_DECLARE_PROVIDER nel file di intestazione.

Registrare l'handle del provider

Prima di poter usare l'handle del provider per registrare gli eventi, è necessario chiamare TraceLoggingRegister per registrare l'handle del provider. Questa operazione viene in genere eseguita in main() o DLLMain(), ma può essere eseguita in qualsiasi momento, purché precede qualsiasi tentativo di registrare un evento. Se si registra un evento prima di registrare l'handle del provider, non verrà generato alcun errore, ma l'evento non verrà registrato. Il codice seguente dell'esempio precedente registra l'handle del provider.

// Define the GUID to use in TraceLoggingProviderRegister
TRACELOGGING_DEFINE_PROVIDER(
    g_hMyComponentProvider,
    "SimpleTraceLoggingProvider",
    // {0205c616-cf97-5c11-9756-56a2cee02ca7}
    (0x0205c616,0xcf97,0x5c11,0x97,0x56,0x56,0xa2,0xce,0xe0,0x2c,0xa7));

void main()
{
    char sampleValue[] = "Sample value";

    // Register the provider
    TraceLoggingRegister(g_hMyComponentProvider);

Registrare un evento tracelogging

Dopo la registrazione del provider, il codice seguente registra un evento semplice.

    // 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).

La macro TraceLoggingWrite accetta fino a nove argomenti. Il nome dell'evento viene archiviato in formato UTF-8. Non è necessario utilizzare caratteri incorporati '\0' nel nome dell'evento o nei nomi dei campi. Non esistono altri limiti per i caratteri consentiti, anche se alcuni decodificatori di eventi o processori di eventi potrebbero avere limitazioni proprie.

Ogni argomento che segue il nome dell'evento deve essere sottoposto a wrapping all'interno di una macro Wrapper TraceLogging. Se si usa C++, è possibile utilizzare la TraceLoggingValue macro wrapper per dedurre automaticamente il tipo dell'argomento. Se si scrive in C o se si desidera un maggiore controllo sul tipo di campo, è necessario usare macro di campo specifiche del tipo, ad TraceLoggingInt32esempio , TraceLoggingUnicodeString, TraceLoggingStringe così via.

Oltre a registrare singoli eventi, è anche possibile raggruppare gli eventi in base all'attività usando traceLoggingWriteActivity o TraceLoggingWriteStart/TraceLoggingWriteStop disponibili in TraceLoggingActivity.h. Le attività correlano gli eventi e sono utili per gli scenari che hanno un inizio e una fine. Ad esempio, è possibile usare un'attività per misurare uno scenario che inizia con l'avvio di un'applicazione, include il tempo necessario per la schermata iniziale diventa disponibile e termina quando la schermata iniziale dell'applicazione diventa visibile.

Le attività acquisiscono singoli eventi e annidano altre attività che si verificano tra l'inizio e la fine di tale attività. Le attività hanno un ambito per processo e devono essere passate dal thread al thread per annidare correttamente gli eventi multithread.

L'ambito di un handle del provider è limitato al modulo (FILE DLL, EXE o SYS) in cui è definito. L'handle non deve essere passato ad altre DLL. Se una macro TraceLoggingWrite viene richiamata in A.DLL utilizzando un handle del provider definito in B.DLL, può causare problemi. Il modo più sicuro ed efficiente per soddisfare questo requisito consiste nel fare riferimento direttamente all'handle del provider globale e non passare mai l'handle del provider come parametro.

Annullare la registrazione del provider

Prima di scaricare il componente, è necessario annullare la registrazione del provider TraceLogging. Ciò è particolarmente importante per DLL e driver. È probabile che si verifichi un arresto anomalo se una DLL o un driver si scarica senza annullare la registrazione del provider.

Il codice seguente annulla la registrazione del provider:

// Stop TraceLogging and unregister the provider
TraceLoggingUnregister(g_hMyComponentProvider);

Compatibilità

A seconda della configurazione, TraceLoggingProvider.h può essere compatibile con le versioni precedenti (il programma risultante verrà eseguito inWindows Vista o versioni successive) o può essere ottimizzato per le versioni successive del sistema operativo. TraceLoggingProvider.h usa WINVER (modalità utente) e NTDDI_VERSION (modalità kernel) per determinare se deve essere compatibile con le versioni precedenti del sistema operativo o essere ottimizzato per le versioni più recenti del sistema operativo.

Per la modalità utente, se si include <windows.h> prima di impostare WINVER, <windows.h> imposta WINVER sulla versione predefinita del sistema operativo di destinazione dell'SDK. Se WINVER è impostato su 0x602 o versione successiva, TraceLoggingProvider.h ottimizza il comportamento per Windows 8 o versione successiva e l'app non verrà eseguita nelle versioni precedenti di Windows. Se è necessario che il programma venga eseguito in Vista o Windows 7, assicurarsi di impostare WINVER sul valore appropriato prima di includere <windows.h>.

Analogamente, se si include <wdm.h> prima di impostare NTDDI_VERSION, <wdm.h> imposta NTDDI_VERSION su un valore predefinito. Se NTDDI_VERSION è impostato su 0x06040000 o versione successiva, TraceLoggingProvider.h ottimizza il comportamento per Windows 10 e il driver non funzionerà nelle versioni precedenti di Windows.

Questo comportamento può essere controllato impostando TLG_HAVE_EVENT_SET_INFORMATION prima di includere TraceLoggingProvider.h. Per informazioni dettagliate sulla TLG_HAVE_EVENT_SET_INFORMATION macro, vedere i commenti nell'intestazioneTraceLoggingProvider.h.

Riepilogo e passaggi successivi

Per informazioni su come acquisire e visualizzare i dati traceLogging usando Windows Performance Tools (WPT), vedere Registrare e visualizzare gli eventi traceLogging.

Per altri esempi di traceLogging C /C++, vedere Esempi di traccia C/C++ .