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.h
verwendet 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
, TraceLoggingString
usw. 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.h
von 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 .