Freigeben über


TraceLogging C/C++-Schnellstart

Im folgenden Abschnitt werden die grundlegenden Schritte beschrieben, die zum Hinzufügen von TraceLogging zu C/C++-Benutzermoduscode erforderlich sind.

Voraussetzungen

  • Visual Studio 2013 oder eine neuere Version.
  • Windows 10 Software Development Kit (SDK) ist erforderlich, um einen Benutzermodusanbieter zu schreiben.
  • Windows Driver Kit (WDK) für Windows 10 ist erforderlich, um einen Kernelmodusanbieter zu schreiben.

Wichtig

Um Linkerfehler für ungelöste EventRegister, EventWriteTransfer- oder EventUnregister Funktionen zu vermeiden, verknüpfen Sie beim Kompilieren dieser Beispiele mit advapi32.lib .

Um Ereignisse aus diesen Beispielen zu sammeln und zu decodieren, müssen Sie eine Ablaufverfolgung mithilfe eines Tools wie tracelog oder traceview starten, das Beispiel ausführen, die Ablaufverfolgung mit einem Tool wie tracelog oder traceview beenden und die Ablaufverfolgung mithilfe eines Decodierungstools wie tracefmt oder traceview decodieren. Wenn mein Anbieter beispielsweise mithilfe der GUID {0205c616-cf97-5c11-9756-56a2cee02ca7}definiert wurde, kann ich die Ereignisse aus diesen Beispielen mit den Windows SDK-Tools tracelog und tracefmt wie folgt anzeigen:

  • tracelog -start MyTraceSession -f MyTraceFile.etl -guid #0205c616-cf97-5c11-9756-56a2cee02ca7
  • Führen Sie das Beispiel aus.
  • tracelog -stop MyTraceSession
  • tracefmt -o MyTraceFile.txt MyTraceFile.etl
  • notepad MyTraceFile.txt

SimpleTraceLoggingExample.h

Dieser Beispielheader enthält die TraceLogging-APIs und deklariert das Anbieterhandle, das zum Protokollieren von Ereignissen verwendet wird. Jede Klasse, die TraceLogging verwenden möchte, enthält diesen Header und kann dann mit der Protokollierung beginnen.

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

Die Headerdatei enthält TraceLoggingProvider.h , die die C/C++-TraceLogging-API definiert. Sie müssen zuerst einschließen windows.h , da sie konstanten definiert, die von TraceLoggingProvider.hverwendet werden.

Die Headerdateiweiterleitung deklariert das Anbieterhandle g_hMyComponentProvider , das Sie an die TraceLogging-APIs übergeben, um Ereignisse zu protokollieren. Auf dieses Handle muss jeder Code zugreifen können, der TraceLogging verwenden möchte.

TRACELOGGING_DECLARE_PROVIDER ist ein Makro, das ein extern const TraceLoggingHProvider Handle mit dem von Ihnen angegebenen Namen erstellt, der im obigen Beispiel lautet g_hMyComponentProvider. Sie ordnen die tatsächliche Anbieterhandlevariable in einer Codedatei zu.

SimpleTraceLoggingExample.cpp

Im folgenden Beispiel wird der Anbieter registriert, ein Ereignis protokolliert und die Registrierung des Anbieters aufgehoben.

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

Das obige Beispiel enthält SimpleTraceLoggingExample.h, die die globale Anbietervariable enthält, die Ihr Code zum Protokollieren von Ereignissen verwendet.

Das TRACELOGGING_DEFINE_PROVIDER Makro weist Speicher zu und definiert die Anbieterhandlevariable. Der Variablenname, den Sie für dieses Makro angeben, muss mit dem Namen übereinstimmen, den Sie im TRACELOGGING_DECLARE_PROVIDER Makro in Ihrer Headerdatei verwendet haben.

Registrieren des Anbieterhandles

Bevor Sie das Anbieterhandle zum Protokollieren von Ereignissen verwenden können, müssen Sie TraceLoggingRegister aufrufen, um Ihr Anbieterhandle zu registrieren. Dies geschieht in der Regel in Standard() oder DLLMain(), kann jedoch jederzeit ausgeführt werden, solange es jedem Versuch vorausgeht, ein Ereignis zu protokollieren. Wenn Sie ein Ereignis vor der Registrierung des Anbieterhandles protokollieren, tritt kein Fehler auf, aber das Ereignis wird nicht protokolliert. Der folgende Code aus dem obigen Beispiel registriert das Anbieterhandle.

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

Protokollieren eines Ablaufverfolgungsereignisses

Nachdem der Anbieter registriert wurde, protokolliert der folgende Code ein einfaches Ereignis.

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

Das Makro TraceLoggingWrite akzeptiert bis zu neunundneunzig Argumente. Der Ereignisname wird im UTF-8-Format gespeichert. Sie dürfen keine eingebetteten '\0' Zeichen im Ereignis- oder Feldnamen verwenden. Es gibt keine anderen Einschränkungen für zulässige Zeichen, obwohl einige Ereignisdecoder oder Ereignisprozessoren möglicherweise eigene Einschränkungen haben.

Jedes Argument, das dem Ereignisnamen folgt, muss innerhalb eines TraceLogging Wrapper-Makros umschlossen werden. Wenn Sie C++ verwenden, können Sie das TraceLoggingValue Wrappermakro verwenden, um automatisch den Typ des Arguments abzuleiten. Wenn Sie in C schreiben oder mehr Kontrolle über den Feldtyp haben möchten, müssen Sie typspezifische Feldmakros wie TraceLoggingInt32, , TraceLoggingUnicodeString, TraceLoggingStringusw. verwenden.

Zusätzlich zur Protokollierung einzelner Ereignisse können Sie Ereignisse auch nach Aktivität gruppieren, indem Sie die Makros TraceLoggingWriteActivity oder TraceLoggingWriteStart/TraceLoggingWriteStop in TraceLoggingActivity.h verwenden. Aktivitäten korrelieren Ereignisse und sind nützlich für Szenarien mit einem Anfang und einem Ende. Sie können beispielsweise eine Aktivität verwenden, um ein Szenario zu messen, das mit dem Start einer Anwendung beginnt, die Zeit einschließt, die benötigt wird, bis der Begrüßungsbildschirm verfügbar wird und endet, wenn der Anfangsbildschirm der Anwendung sichtbar wird.

Aktivitäten erfassen einzelne Ereignisse und schachteln andere Aktivitäten, die zwischen Beginn und Ende dieser Aktivität auftreten. Aktivitäten verfügen über einen Prozessbereich und müssen vom Thread an den Thread übergeben werden, um Multithreadereignisse ordnungsgemäß zu schachteln.

Der Bereich eines Anbieterhandles ist auf das Modul (DLL, EXE oder SYS-Datei) beschränkt, in dem es definiert ist. Das Handle sollte nicht an andere DLLs übergeben werden. Wenn ein TraceLoggingWrite-Makro in A.DLL mithilfe eines in B.DLL definierten Anbieterhandles aufgerufen wird, kann dies zu Problemen führen. Die sicherste und effizienteste Möglichkeit, diese Anforderung zu erfüllen, besteht darin, immer direkt auf das globale Anbieterhandle zu verweisen und niemals das Anbieterhandle als Parameter zu übergeben.

Aufheben der Registrierung des Anbieters

Bevor Die Komponente entladen wird, müssen Sie die Registrierung des TraceLogging-Anbieters aufheben. Dies ist besonders wichtig für DLLs und Treiber. Ein Absturz tritt wahrscheinlich auf, wenn eine DLL oder ein Treiber entladen wird, ohne die Registrierung des Anbieters aufzuheben.

Der folgende Code hebt die Registrierung des Anbieters auf:

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

Kompatibilität

Je nach Konfiguration kann TraceLoggingProvider.h abwärtskompatibel sein (das resultierende Programm wird unter Windows Vista oder höher ausgeführt) oder für spätere Betriebssystemversionen optimiert werden. TraceLoggingProvider.h verwendet WINVER (Benutzermodus) und NTDDI_VERSION (Kernelmodus), um zu bestimmen, ob es mit früheren Betriebssystemversionen kompatibel oder für neuere Betriebssystemversionen optimiert werden soll.

Wenn Sie für den Benutzermodus einschließen <windows.h> , bevor Sie WINVER festlegen, <windows.h> legt WINVER auf die Standardzielbetriebssystemversion des SDK fest. Wenn WINVER auf 0x602 oder höher festgelegt ist, TraceLoggingProvider.h optimiert das Verhalten für Windows 8 oder höher, und Ihre App wird nicht unter früheren Versionen von Windows ausgeführt. Wenn Ihr Programm unter Vista oder Windows 7 ausgeführt werden soll, müssen Sie WINVER auf den entsprechenden Wert festlegen, bevor Sie einschließen <windows.h>.

Wenn Sie vor dem Festlegen NTDDI_VERSION einschließen <wdm.h> , <wdm.h> wird NTDDI_VERSION auf einen Standardwert festgelegt. Wenn NTDDI_VERSION auf 0x06040000 oder höher festgelegt ist, optimiert TraceLoggingProvider.h sein Verhalten für Windows 10, und Ihr Treiber funktioniert nicht in früheren Versionen von Windows.

Dieses Verhalten kann durch Festlegen TLG_HAVE_EVENT_SET_INFORMATION von vor dem Einschließen TraceLoggingProvider.hvon gesteuert werden. Ausführliche Informationen zum Makro finden Sie in den TraceLoggingProvider.h Kommentaren TLG_HAVE_EVENT_SET_INFORMATION im Header.

Zusammenfassung und nächste Schritte

Informationen zum Erfassen und Anzeigen von TraceLogging-Daten mithilfe der Windows-Leistungstools (WPT) finden Sie unter Aufzeichnen und Anzeigen von Ablaufverfolgungsereignissen.

Weitere C ++-TraceLogging-Beispiele finden Sie unter C/C++-Ablaufprotokollierungsbeispiele .