Hinzufügen der Ereignisablaufverfolgung zu Kernelmodustreibern

In diesem Abschnitt wird beschrieben, wie Sie die Kernelmodus-API für Windows (ETW) zum Hinzufügen der Ereignisablaufverfolgung zu Kernelmodustreibern verwenden. Die ETW-Kernelmodus-API wurde mit Windows Vista eingeführt und wird in früheren Betriebssystemen nicht unterstützt. Verwenden Sie die WPP-Softwareablaufverfolgung oder WMI-Ereignisablaufverfolgung, wenn Ihr Treiber die Ablaufverfolgungsfunktion in Windows 2000 und höher unterstützen muss.

Tipp

Informationen zum Anzeigen von Beispielcode zur Implementierung von ETW mit dem Windows Driver Kit (WDK) und Visual Studio finden Sie im Eventdrv-Beispiel.

Inhalt dieses Abschnitts:

Workflow – Hinzufügen der Ereignisablaufverfolgung zu Kernelmodustreibern

1. Entscheiden Sie, welche Art von Ereignissen sie auslösen und wo sie veröffentlicht werden sollen.

2. Erstellen Sie ein Instrumentierungsmanifest, das den Anbieter, die Ereignisse und Kanäle definiert.

3. Kompilieren des Instrumentierungsmanifests mithilfe des Nachrichtencompilers (Mc.exe)

4. Fügen Sie den generierten Code hinzu, um die Ereignisse auszuheben (veröffentlichen) (Registrieren, Aufheben der Registrierung und Schreiben von Ereignissen)

5. Erstellen des Treibers

6. Installieren des Manifests

7. Testen Sie den Treiber, um die ETW-Unterstützung zu überprüfen.

Workflow – Hinzufügen der Ereignisablaufverfolgung zu Kernelmodustreibern

Flussdiagramm, das den Prozess zum Hinzufügen der Ereignisablaufverfolgung zu Kernelmodustreibern zeigt.

1. Entscheiden Sie, welche Art von Ereignissen sie auslösen und wo sie veröffentlicht werden sollen.

Bevor Sie mit dem Codieren beginnen, müssen Sie entscheiden, welche Art von Ereignissen der Treiber über die Ereignisablaufverfolgung für Windows (ETW) protokollieren soll. Sie können z. B. Ereignisse protokollieren, die Ihnen helfen können, Probleme nach der Verteilung des Treibers zu diagnostizieren, oder Ereignisse, die Ihnen beim Entwickeln des Treibers helfen können. Weitere Informationen finden Sie unter Windows-Ereignisprotokollreferenz.

Die Ereignistypen werden mit Kanälen identifiziert. Ein Kanal ist ein benannter Ereignisstrom vom Typ "Admin", "Operational", "Analytical" oder "Debug", der auf eine bestimmte Zielgruppe gerichtet ist, ähnlich einem Fernsehkanal. Ein Kanal liefert die Ereignisse vom Ereignisanbieter an die Ereignisprotokolle und Ereigniskonsumenten. Weitere Informationen finden Sie unter Definieren von Kanälen.

Während der Entwicklung interessieren Sie sich wahrscheinlich für Ablaufverfolgungsereignisse, mit denen Sie Ihren Code debuggen können. Dieser Kanal kann im Produktionscode verwendet werden, um Probleme zu beheben, die nach der Bereitstellung des Treibers auftreten können. Möglicherweise möchten Sie auch Ereignisse nachverfolgen, die zum Messen der Leistung verwendet werden können. Diese Ereignisse können IT-Experten dabei helfen, die Serverleistung zu optimieren und Netzwerkengpässe zu identifizieren.

2. Erstellen Sie ein Instrumentierungsmanifest, das den Anbieter, die Ereignisse und Kanäle definiert.

Das Instrumentierungsmanifest ist eine XML-Datei, die eine formale Beschreibung der Ereignisse bereitstellt, die ein Anbieter auslöst. Das Instrumentierungsmanifest identifiziert den Ereignisanbieter, gibt den Kanal oder die Kanäle (bis zu acht) an und beschreibt die Ereignisse und vorlagen, die die Ereignisse verwenden. Darüber hinaus ermöglicht das Instrumentierungsmanifest die Lokalisierung von Zeichenfolgen, sodass Sie die Ablaufverfolgungsmeldungen lokalisieren können. Das Ereignissystem und die Ereigniskonsumenten können die im Manifest bereitgestellten strukturierten XML-Daten verwenden, um Abfragen und Analysen durchzuführen.

Informationen zum Instrumentierungsmanifest finden Sie unter Schreiben eines Instrumentierungsmanifestmanifests (Windows), des EventManifest-Schemas (Windows) und des Verwendens des Windows-Ereignisprotokolls (Windows).

Das folgende Instrumentierungsmanifest zeigt einen Ereignisanbieter, der den Namen "Beispieltreiber" verwendet. Beachten Sie, dass dieser Name nicht mit dem Namen der Treiber-Binärdatei identisch sein muss. Das Manifest gibt außerdem eine GUID für den Anbieter und die Pfade zu den Nachrichten- und Ressourcendateien an. Die Nachrichten- und Ressourcendateien teilen ETW mit, wo die zum Decodieren und Melden der Ereignisse erforderlichen Ressourcen gefunden werden sollen. Diese Pfade verweisen auf den Speicherort der Treiberdatei (.sys). Der Treiber muss im angegebenen Verzeichnis auf dem Zielcomputer installiert sein.

Im Beispiel wird das benannte Kanalsystem verwendet, ein Kanal für Ereignisse vom Typ "Admin". Dieser Kanal wird in der datei Winmeta.xml definiert, die mit dem Windows Driver Kit (WDK) im Verzeichnis %WindowsSdkDir%\include\um bereitgestellt wird. Der Systemkanal ist für Anwendungen gesichert, die unter Systemdienstkonten ausgeführt werden. Das Manifest enthält die Ereignisvorlagen, die die Datentypen beschreiben, die bei der Veröffentlichung der Ereignisse bereitgestellt werden, sowie deren statische und dynamische Inhalte. Dieses Beispielmanifest definiert drei Ereignisse: StartEvent, , SampleEventAund UnloadEvent.

Zusätzlich zu Kanälen können Sie Ereignisse ebenen und Schlüsselwörtern zuordnen. Schlüsselwörter und Ebenen bieten eine Möglichkeit, Ereignisse zu aktivieren und einen Mechanismus zum Filtern von Ereignissen bereitzustellen, wenn sie veröffentlicht werden. Schlüsselwörter können verwendet werden, um logisch verwandte Ereignisse zusammen zu gruppieren. Eine Ebene kann verwendet werden, um den Schweregrad oder die Ausführlichkeit eines Ereignisses anzugeben, z. B. kritisch, Fehler, Warnung oder Information. Die datei Winmeta.xml enthält vordefinierte Werte für Ereignisattribute.

Wenn Sie eine Vorlage für die Ereignisnutzlast (Ereignisnachricht und Daten) erstellen, müssen Sie die Eingabe- und Ausgabetypen angeben. Die unterstützten Typen werden im Abschnitt "Hinweise" von InputType Complex Type (Windows) beschrieben.

<?xml version='1.0' encoding='utf-8' standalone='yes'?>
<instrumentationManifest
    xmlns="http://schemas.microsoft.com/win/2004/08/events"
    xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://schemas.microsoft.com/win/2004/08/events eventman.xsd"
    >
  <instrumentation>
    <events>
      <provider
          guid="{b5a0bda9-50fe-4d0e-a83d-bae3f58c94d6}"
          messageFileName="%SystemDrive%\ETWDriverSample\Eventdrv.sys"
          name="Sample Driver"
          resourceFileName="%SystemDrive%\ETWDriverSample\Eventdrv.sys"
          symbol="DriverControlGuid"
          >
        <channels>
          <importChannel
              chid="SYSTEM"
              name="System"
              />
        </channels>
        <templates>
          <template tid="tid_load_template">
            <data
                inType="win:UInt16"
                name="DeviceNameLength"
                outType="xs:unsignedShort"
                />
            <data
                inType="win:UnicodeString"
                name="name"
                outType="xs:string"
                />
            <data
                inType="win:UInt32"
                name="Status"
                outType="xs:unsignedInt"
                />
          </template>
          <template tid="tid_unload_template">
            <data
                inType="win:Pointer"
                name="DeviceObjPtr"
                outType="win:HexInt64"
                />
          </template>
        </templates>
        <events>
          <event
              channel="SYSTEM"
              level="win:Informational"
              message="$(string.StartEvent.EventMessage)"
              opcode="win:Start"
              symbol="StartEvent"
              template="tid_load_template"
              value="1"
              />
          <event
              channel="SYSTEM"
              level="win:Informational"
              message="$(string.SampleEventA.EventMessage)"
              opcode="win:Info"
              symbol="SampleEventA"
              value="2"
              />
          <event
              channel="SYSTEM"
              level="win:Informational"
              message="$(string.UnloadEvent.EventMessage)"
              opcode="win:Stop"
              symbol="UnloadEvent"
              template="tid_unload_template"
              value="3"
              />
        </events>
      </provider>
    </events>
  </instrumentation>
  <localization xmlns="http://schemas.microsoft.com/win/2004/08/events">
    <resources culture="en-US">
      <stringTable>
        <string
            id="StartEvent.EventMessage"
            value="Driver Loaded"
            />
        <string
            id="SampleEventA.EventMessage"
            value="IRP A Occurred"
            />
        <string
            id="UnloadEvent.EventMessage"
            value="Driver Unloaded"
            />
      </stringTable>
    </resources>
  </localization>
</instrumentationManifest>

3. Kompilieren des Instrumentierungsmanifests mithilfe des Nachrichtencompilers (Mc.exe)

Der Nachrichtencompiler (Mc.exe) muss ausgeführt werden, bevor Sie den Quellcode kompilieren. Der Nachrichtencompiler ist im Windows Driver Kit (WDK) enthalten. Der Nachrichtencompiler erstellt eine Headerdatei, die Definitionen für den Ereignisanbieter, Ereignisattribute, Kanäle und Ereignisse enthält. Sie müssen diese Headerdatei in Den Quellcode einschließen. Der Nachrichtencompiler platziert auch das generierte Ressourcencompilerskript (*.rc) und die generierten .bin Dateien (Binäre Ressourcen), die das Ressourcencompilerskript enthält.

Sie können diesen Schritt als Teil Des Buildprozesses auf verschiedene Arten einschließen:

  • Hinzufügen der Message Compiler-Aufgabe zur Treiberprojektdatei (wie im Eventdrv-Beispiel gezeigt).

  • Verwenden von Visual Studio zum Hinzufügen des Instrumentierungsmanifests und zum Konfigurieren der Message Compiler-Eigenschaften.

Hinzufügen einer Nachrichtencompileraufgabe zur Projektdatei Ein Beispiel dafür, wie Sie den Nachrichtencompiler in den Buildprozess einbeziehen können, finden Sie in der Projektdatei für das Eventdrv-Beispiel. In der Eventdrv.vcxproj Datei gibt es einen <MessageCompile-Abschnitt, der den Nachrichtencompiler> aufruft. Der Nachrichtencompiler verwendet die Manifestdatei (evntdrv.xml) als Eingabe, um die Headerdatei evntdrvEvents.h zu generieren. In diesem Abschnitt werden auch die Pfade für die generierten RC-Dateien angegeben und die Protokollierungsmakros im Kernelmodus aktiviert. Sie können diesen Abschnitt kopieren und ihrer Treiberprojektdatei (.vcxproj) hinzufügen.


    <MessageCompile Include="evntdrv.xml">
      <GenerateKernelModeLoggingMacros>true</GenerateKernelModeLoggingMacros>
      <HeaderFilePath>.\$(IntDir)</HeaderFilePath>
      <GeneratedHeaderPath>true</GeneratedHeaderPath>
      <WinmetaPath>"$(SDK_INC_PATH)\winmeta.xml"</WinmetaPath>
      <RCFilePath>.\$(IntDir)</RCFilePath>
      <GeneratedRCAndMessagesPath>true</GeneratedRCAndMessagesPath>
      <GeneratedFilesBaseName>evntdrvEvents</GeneratedFilesBaseName>
      <UseBaseNameOfInput>true</UseBaseNameOfInput>
    </MessageCompile>

Beim Erstellen des Eventdrv.sys-Beispiels erstellt Visual Studio die erforderlichen Dateien für die Ereignisablaufverfolgung. Außerdem wird das evntdrv.xml Manifest der Liste der Ressourcendateien für das Treiberprojekt hinzugefügt. Sie können das Manifest auswählen und halten (oder mit der rechten Maustaste darauf klicken), um die Eigenschaftenseiten des Nachrichtencompilers anzuzeigen.

Verwenden von Visual Studio zum Hinzufügen des Instrumentierungsmanifests

Sie können dem Treiberprojekt das Instrumentierungsmanifest hinzufügen und dann die Nachrichtencompilereigenschaften konfigurieren, um die erforderlichen Ressourcen- und Headerdateien zu erstellen.

So fügen Sie das Instrumentierungsmanifest mithilfe von Visual Studio dem Projekt hinzu

  1. Fügen Sie im Projektmappen-Explorer die Manifestdatei zum Treiberprojekt hinzu. Wählen Und halten Sie (oder klicken Sie mit der rechten Maustaste darauf) Ressourcendateien > "Vorhandenes Element hinzufügen>" (z. B. evntdrv.xml oder "mydriver.man").

  2. Wählen Sie die soeben hinzugefügte Datei aus und halten Sie sie gedrückt (oder klicken Sie mit der rechten Maustaste darauf), und verwenden Sie die Eigenschaftenseiten, um den Elementtyp in MessageCompile zu ändern, und wählen Sie "Übernehmen" aus.

  3. Die Eigenschaften des Nachrichtencompilers werden angezeigt. Legen Sie unter den allgemeinen Einstellungen die folgenden Optionen fest, und wählen Sie dann "Übernehmen" aus.

    Allgemein Einstellung
    Kernelmodusprotokollierungsmakros generieren Ja (-km)
    Verwenden des Basisnamens der Eingabe Ja (-b)
  4. Legen Sie unter "Dateioptionen" die folgenden Optionen fest, und wählen Sie dann "Übernehmen" aus.

    Dateioptionen Einstellung
    Generieren der Headerdatei für den Zähler Ja
    Headerdateipfad $(IntDir)
    Generierter RC- und Binärnachrichtendateien-Pfad Ja
    RC-Dateipfad $(IntDir)
    Basisname der generierten Dateien $(Filename)

Standardmäßig verwendet der Nachrichtencompiler den Basisnamen der Eingabedatei als Basisnamen der von ihr generierten Dateien. Um einen Basisnamen anzugeben, legen Sie das Feld "Basisname für generierte Dateien" (-z) fest. Im Eventdr.sys Beispiel wird der Basisname auf "evntdrvEvents" festgelegt, sodass er mit dem Namen der Headerdatei "evntdrvEvents.h" übereinstimmt, die in "evntdrv.c" enthalten ist.

Hinweis

Wenn Sie die generierte RC-Datei nicht in Ihr Visual Studio-Projekt einschließen, erhalten Sie möglicherweise Fehlermeldungen zu Ressourcen, die beim Installieren der Manifestdatei nicht gefunden wurden.

4. Fügen Sie den generierten Code hinzu, um die Ereignisse auszuheben (veröffentlichen) (Registrieren, Aufheben der Registrierung und Schreiben von Ereignissen)

Im Instrumentierungsmanifest haben Sie die Namen des Ereignisanbieters und der Ereignisdeskriptoren definiert. Wenn Sie das Instrumentierungsmanifest mit dem Nachrichtencompiler kompilieren, generiert der Nachrichtencompiler eine Headerdatei, die die Ressourcen beschreibt und auch Makros für die Ereignisse definiert. Jetzt müssen Sie dem Treiber den generierten Code hinzufügen, um diese Ereignisse auszuheben.

  1. Fügen Sie in der Quelldatei die Ereignisheaderdatei hinzu, die vom Nachrichtencompiler (MC.exe) erstellt wird. Im Eventdrv-Beispiel enthält die Quelldatei "Evntdrv.c" beispielsweise die Headerdatei (evntdrvEvents.h), die im vorherigen Schritt generiert wurde:

    #include "evntdrvEvents.h"  
    
  2. Fügen Sie die Makros hinzu, die den Treiber als Ereignisanbieter registrieren und aufheben. Beispielsweise erstellt der Nachrichtencompiler in der Headerdatei für das Eventdrv-Beispiel (evntdrvEvents.h) Makros basierend auf dem Namen des Anbieters. Im Manifest verwendet das Eventdrv-Beispiel den Namen "Sample Driver" als Namen des Anbieters. Der Nachrichtencompiler kombiniert den Namen des Anbieters mit dem Ereignismakro, um den Anbieter zu registrieren, in diesem Fall EventRegisterSample_Driver.

    //  This is the generated header file envtdrvEvents.h
    //
    //  ...
    //
    //
    // Register with ETW Vista +
    //
    #ifndef EventRegisterSample_Driver
    #define EventRegisterSample_Driver() McGenEventRegister(&DriverControlGuid, McGenControlCallbackV2, &DriverControlGuid_Context, &Sample_DriverHandle)
    #endif
    

    Fügen Sie der DriverEntry-Funktion das EventRegister-Anbietermakro<hinzu>. Fügen Sie diese Funktion nach dem Code hinzu, der das Geräteobjekt erstellt und initialisiert. Beachten Sie, dass Sie dem Aufruf der EventRegister-Anbieterfunktion>< mit einem Aufruf des EventUnregister-Anbieters<> entsprechen müssen. Sie können die Registrierung des Treibers in der Unload-Routine Ihres Treibers aufheben.*

       // DriverEntry function
       // ...
    
    
        // Register with ETW
        //
        EventRegisterSample_Driver();
    
  3. Fügen Sie den generierten Code zu den Quelldateien Ihres Treibers hinzu, um die ereignisse zu schreiben (auslösen), die Sie im Manifest angegeben haben. Die aus dem Manifest kompilierte Headerdatei enthält den generierten Code für den Treiber. Verwenden Sie die in der Headerdatei definierten EventWrite-Ereignisfunktionen<>, um Ablaufverfolgungsmeldungen in ETW zu veröffentlichen. Der folgende Code zeigt beispielsweise die Makros für Ereignisse, die in evntdrvEvents.h für das Eventdrv-Beispiel definiert sind.

    Die Makros zum Schreiben dieser Ereignisse werden aufgerufen: EventWriteStartEvent, , EventWriteSampleEventAund EventWriteUnloadEvent. Wie Sie in der Definition dieser Makros sehen können, enthält die Makrodefinition automatisch ein EventEnabled-Ereignismakro<>, das überprüft, ob das Ereignis aktiviert ist. Die Überprüfung beseitigt die Notwendigkeit, die Nutzlast zu erstellen, wenn das Ereignis nicht aktiviert ist.

    
    ///
    // This is the generated header file envtdrvEvents.h
    //
    //  ...
    //
    // Enablement check macro for StartEvent
    //
    
    #define EventEnabledStartEvent() ((Sample_DriverEnableBits[0] & 0x00000001) != 0)
    
    //
    // Event Macro for StartEvent
    //
    #define EventWriteStartEvent(Activity, DeviceNameLength, name, Status)\
            EventEnabledStartEvent() ?\
            Template_hzq(Sample_DriverHandle, &StartEvent, Activity, DeviceNameLength, name, Status)\
            : STATUS_SUCCESS\
    
    //
    // Enablement check macro for SampleEventA
    //
    
    #define EventEnabledSampleEventA() ((Sample_DriverEnableBits[0] & 0x00000001) != 0)
    
    //
    // Event Macro for SampleEventA
    //
    #define EventWriteSampleEventA(Activity)\
            EventEnabledSampleEventA() ?\
            TemplateEventDescriptor(Sample_DriverHandle, &SampleEventA, Activity)\
            : STATUS_SUCCESS\
    
    //
    // Enablement check macro for UnloadEvent
    //
    
    #define EventEnabledUnloadEvent() ((Sample_DriverEnableBits[0] & 0x00000001) != 0)
    
    //
    // Event Macro for UnloadEvent
    //
    #define EventWriteUnloadEvent(Activity, DeviceObjPtr)\
            EventEnabledUnloadEvent() ?\
            Template_p(Sample_DriverHandle, &UnloadEvent, Activity, DeviceObjPtr)\
            : STATUS_SUCCESS\
    
    

    Fügen Sie die EventWrite-Ereignismakros<> zu Ihrem Quellcode für die Ereignisse hinzu, die Sie auslösen. Der folgende Codeausschnitt zeigt beispielsweise die DriverEntry-Routine aus dem Eventdrv-Beispiel. DriverEntry enthält die Makros zum Registrieren des Treibers bei ETW (EventRegisterSample_Driver) und das Makro zum Schreiben des Treiberereignisses in ETW (EventWriteStartEvent).

    NTSTATUS
    DriverEntry(
        IN PDRIVER_OBJECT DriverObject,
        IN PUNICODE_STRING RegistryPath
        )
    /*++
    
    Routine Description:
    
        Installable driver initialization entry point.
        This entry point is called directly by the I/O system.
    
    Arguments:
    
        DriverObject - pointer to the driver object
    
        RegistryPath - pointer to a unicode string representing the path
            to driver-specific key in the registry
    
    Return Value:
    
       STATUS_SUCCESS if successful
       STATUS_UNSUCCESSFUL  otherwise
    
    --*/
    {
        NTSTATUS Status = STATUS_SUCCESS;
        UNICODE_STRING DeviceName;
        UNICODE_STRING LinkName;
        PDEVICE_OBJECT EventDrvDeviceObject;
        WCHAR DeviceNameString[128];
        ULONG LengthToCopy = 128 * sizeof(WCHAR);
        UNREFERENCED_PARAMETER (RegistryPath);
    
        KdPrint(("EventDrv: DriverEntry\n"));
    
        //
        // Create Dispatch Entry Points.  
        //
        DriverObject->DriverUnload = EventDrvDriverUnload;
        DriverObject->MajorFunction[ IRP_MJ_CREATE ] = EventDrvDispatchOpenClose;
        DriverObject->MajorFunction[ IRP_MJ_CLOSE ] = EventDrvDispatchOpenClose;
        DriverObject->MajorFunction[ IRP_MJ_DEVICE_CONTROL ] = EventDrvDispatchDeviceControl;
    
        RtlInitUnicodeString( &DeviceName, EventDrv_NT_DEVICE_NAME );
    
        //
        // Create the Device object
        //
        Status = IoCreateDevice(
                               DriverObject,
                               0,
                               &DeviceName,
                               FILE_DEVICE_UNKNOWN,
                               0,
                               FALSE,
                               &EventDrvDeviceObject);
    
        if (!NT_SUCCESS(Status)) {
            return Status;
        }
    
        RtlInitUnicodeString( &LinkName, EventDrv_WIN32_DEVICE_NAME );
        Status = IoCreateSymbolicLink( &LinkName, &DeviceName );
    
        if ( !NT_SUCCESS( Status )) {
            IoDeleteDevice( EventDrvDeviceObject );
            return Status;
        }
    
     //
     // Choose a buffering mechanism
     //
     EventDrvDeviceObject->Flags |= DO_BUFFERED_IO;
    
     //
     // Register with ETW
     //
     EventRegisterSample_Driver();
    
     //
     // Log an Event with :  DeviceNameLength
     //                      DeviceName
     //                      Status
     //
    
     // Copy the device name into the WCHAR local buffer in order
     // to place a NULL character at the end, since this field is
     // defined in the manifest as a NULL-terminated string
    
     if (DeviceName.Length <= 128 * sizeof(WCHAR)) {
    
         LengthToCopy = DeviceName.Length;
    
     }
    
     RtlCopyMemory(DeviceNameString,
                   DeviceName.Buffer,
                   LengthToCopy);
    
     DeviceNameString[LengthToCopy/sizeof(WCHAR)] = L'\0';
    
     EventWriteStartEvent(NULL, DeviceName.Length, DeviceNameString, Status);
    
     return STATUS_SUCCESS;
    }
    

Fügen Sie alle EventWrite-Ereignismakros<> zu Ihrem Quellcode für die Ereignisse hinzu, die Sie auslösen. Sie können das Eventdrv-Beispiel untersuchen, um zu sehen, wie die anderen beiden Makros für die Ereignisse im Treiberquellcode aufgerufen werden.

  1. Heben Sie die Registrierung des Treibers als Ereignisanbieter mithilfe des EventUnregister-Anbietermakros<aus der generierten Headerdatei auf> .

    Platzieren Sie diesen Funktionsaufruf in der Entladeroutine des Treibers. Nach dem Aufruf des EventUnregister-Anbietermakros>< sollten keine Ablaufverfolgungsaufrufe ausgeführt werden. Fehler beim Aufheben der Registrierung des Ereignisanbieters, wenn der Prozess entladen wird, da alle dem Prozess zugeordneten Rückruffunktionen nicht mehr gültig sind.

        // DriverUnload function
        // ...
        //
    
        //  Unregister the driver as an ETW provider
        //
        EventUnregisterSample_Driver();
    

5. Erstellen des Treibers

Wenn Sie dem Projekt das Instrumentmanifest hinzugefügt und die Nachrichtencompilereigenschaften (MC.exe) konfiguriert haben, können Sie das Treiberprojekt oder die Treiberlösung mit Visual Studio und MSBuild erstellen.

  1. Öffnen Sie die Treiberlösung in Visual Studio.

  2. Erstellen Sie das Beispiel aus dem Menü "Erstellen", indem Sie "Projektmappe erstellen" auswählen. Weitere Informationen zum Erstellen von Lösungen finden Sie unter Building a Driver.

6. Installieren des Manifests

Sie müssen das Manifest auf dem Zielsystem installieren, damit Ereignisanwender (z. B. das Ereignisprotokoll) den Speicherort der Binärdatei finden können, die die Ereignismetadaten enthält. Wenn Sie die Meldungscompilierungsaufgabe zum Treiberprojekt in Schritt 3 hinzugefügt haben, wurde das Instrumentierungsmanifest kompiliert, und die Ressourcendateien wurden generiert, wenn Sie den Treiber erstellt haben. Verwenden Sie das Befehlszeilenprogramm für Windows-Ereignisse (Wevtutil.exe), um das Manifest zu installieren. Die Syntax zum Installieren des Manifests lautet wie folgt:

wevtutil.exe im drivermanifest

Um beispielsweise das Manifest für den Evntdrv.sys Beispieltreiber zu installieren, öffnen Sie ein Eingabeaufforderungsfenster mit erhöhten Rechten (Als Administrator ausführen) zu dem Verzeichnis, in dem sich die evntdrv.xml Datei befindet, und geben Sie den folgenden Befehl ein:

Wevtutil.exe im evntdrv.xml

Wenn Die Ablaufverfolgungssitzung abgeschlossen ist, deinstallieren Sie das Manifest mithilfe der folgenden Syntax.

wevtutil.exe um drivermanifest

So deinstallieren Sie z. B. das Manifest für das Eventdrv-Beispiel:

Wevtutil.exe um evntdrv.xml

7. Testen Sie den Treiber, um die ETW-Unterstützung zu überprüfen.

Installieren Sie den Treiber. Üben Sie den Treiber aus, um Ablaufverfolgungsaktivitäten zu generieren. Zeigen Sie die Ergebnisse im Ereignisanzeige an. Sie können auch Tracelog ausführen und dann Tracerpt ausführen, ein Tool zum Verarbeiten von Ereignisablaufverfolgungsprotokollen, um die Ereignisablaufverfolgungsprotokolle zu steuern, zu sammeln und anzuzeigen.