Condividi tramite


Aggiungere la traccia software WPP a un driver Windows

Per usare il tracciamento software WPP in un provider di traccia, ad esempio un driver in modalità kernel o un'applicazione in modalità utente, è necessario aggiungere codice (o instrumentare) i file di origine del driver e modificare il progetto del driver. In questa sezione verranno descritti questi passaggi.

Annotazioni

Il modo più semplice per aggiungere traccia WPP al driver consiste nell'usare uno dei modelli di driver KMDF o UMDF in Visual Studio. Se usi i modelli, gran parte del codice che devi aggiungere è già stata predisposta per te. In Visual Studio selezionare File > nuovo > progetto e quindi selezionare il progetto WDF Windows Driver (modalità utente o kernel). Le macro WPP vengono definite nel file di intestazione Trace.h incluso come parte del progetto. Se si usa uno dei modelli, è possibile passare al passaggio 5.

Passaggio 1: Definire il GUID del controllo e i flag di traccia

Ogni provider di traccia (ad esempio un driver o un'app in modalità utente) deve essere definito in modo univoco. A tale scopo, aggiungere la macro WPP_CONTROL_GUIDS che definisce un GUID del controllo, un identificatore e i flag di traccia. Questa operazione viene eseguita in modo da poter identificare e controllare quando e cosa si vuole tracciare. Anche se ogni driver ha in genere un GUID di controllo separato, un driver potrebbe avere più GUID di controllo o più driver potrebbero condividere un GUID di controllo.

Per praticità, la macro WPP_CONTROL_GUIDS viene in genere definita in un file di intestazione comune. Per effettuare il tracciamento, il file di intestazione deve essere incluso (#include) in qualsiasi file di origine che si intende instrumentare.

Per aggiungere WPP_CONTROL_GUIDS macro al driver:

  1. Aggiungere un nuovo file header C++ al progetto di Visual Studio che puoi utilizzare per definire le macro di traccia WPP. Ad esempio, selezionare e tenere premuto (o fare clic con il pulsante destro del mouse) sul driver in Esplora soluzioni e selezionare Aggiungi > nuovo elemento. Salvare il file (ad esempio, come Trace.h).

  2. Aggiungere una macro WPP_CONTROL_GUIDS per specificare un nome descrittivo per il provider di traccia, definire un GUID del controllo e definire i flag di traccia che è possibile usare per qualificare messaggi di traccia specifici.

    La macro WPP_CONTROL_GUIDS ha la sintassi seguente:

    Sintassi per WPP_CONTROL_GUIDS

    #define WPP_CONTROL_GUIDS \
        WPP_DEFINE_CONTROL_GUID(GUIDFriendlyName, (ControlGUID),  \
            WPP_DEFINE_BIT(NameOfTraceFlag1)  \
            WPP_DEFINE_BIT(NameOfTraceFlag2)  \
            .............................   \
            .............................   \
            WPP_DEFINE_BIT(NameOfTraceFlag31) \
            )
    

    Ad esempio, il codice seguente usa myDriverTraceGuid come GUIDFriendlyName. Si noti che ControlGUID ha un formato leggermente diverso rispetto al formato standard di un GUID esadecimale a 32 cifre. ControlGUID include cinque campi di dati, ma sono separati da virgole e racchiusi tra parentesi tonde, invece dei soliti trattini e parentesi graffe. Ad esempio, si specifica ((84bdb2e9,829e,41b3,b891,02f454bc2bd7) anziché {84bdb2e9-829e-41b3-b891-02f454bc2bd7}.

    Esempio di istruzione WPP_CONTROL_GUIDS

    #define WPP_CONTROL_GUIDS                                              \
        WPP_DEFINE_CONTROL_GUID(                                           \
            myDriverTraceGuid, (84bdb2e9,829e,41b3,b891,02f454bc2bd7), \
            WPP_DEFINE_BIT(MYDRIVER_ALL_INFO)        /* bit  0 = 0x00000001 */ \
            WPP_DEFINE_BIT(TRACE_DRIVER)             /* bit  1 = 0x00000002 */ \
            WPP_DEFINE_BIT(TRACE_DEVICE)             /* bit  2 = 0x00000004 */ \
            WPP_DEFINE_BIT(TRACE_QUEUE)              /* bit  3 = 0x00000008 */ \
            )                             
    

    Annotazioni

    È possibile copiare questo frammento di codice in un file di intestazione. Assicurati di modificare il GUID del controllo e il nome descrittivo. È possibile usare GUIDgen.exe per generare il GUID del controllo. Il Guidgen.exe è incluso in Visual Studio (Strumenti > Crea GUID). È anche possibile usare lo strumento Uuidgen.exe, disponibile nella finestra del prompt dei comandi di Visual Studio (digitare uuidgen.exe /? per altre informazioni).

  3. Definire i flag di traccia per il provider di tracciamento.

    Gli elementi WPP_DEFINE_BIT della macro WPP_CONTROL_GUIDS definiscono i flag di traccia per il provider di traccia. In genere, i flag rappresentano livelli di report sempre più dettagliati, ma è possibile usare i flag come qualsiasi modo in cui si preferisce come condizioni per la generazione di messaggi di traccia. Nell'esempio WPP_CONTROL_GUIDS il WPP_DEFINE_BIT definisce quattro flag di traccia (MYDRIVER_ALL_INFO, TRACE_DRIVER, TRACE_DEVICE e TRACE_QUEUE).

    È possibile definire fino a 31 flag di traccia. WPP assegna valori di bit agli elementi nell'ordine in cui vengono visualizzati, ad esempio bit 0 (0x1), bit 1 (0x2), bit 2 (0x4), bit 3 (0x8) e così via. I flag di traccia vengono usati quando si aggiungono funzioni del messaggio di traccia al codice sorgente (descritto nel passaggio 5: Instrumentare il codice driver per generare messaggi di traccia nei punti appropriati).

    Annotazioni

    Usando i flag di traccia è possibile controllare quando tenere traccia di componenti specifici, ad esempio richieste di I/O specifiche o attività di oggetti dispositivo o driver. Si aggiunge il flag di traccia all'istruzione del messaggio di traccia, ad esempio, DoTraceMessage (TRACE_DRIVER, "Hello World!\n"). Quando si crea una sessione di traccia con un controller di traccia, ad esempio Tracelog, si specifica l'opzione -flag da usare per il provider di traccia in tale sessione, in questo caso, il flag è bit 1 (0x1), che corrisponde al flag TRACE_DRIVER. Quando si avvia la sessione di traccia, tutti i messaggi di traccia associati a quel flag di traccia vengono scritti nel log.

Passaggio 2: Scegliere le funzioni del messaggio di traccia che si intende usare e definire le macro WPP per tali funzioni

Analogamente a una funzione di stampa di debug, una funzione del messaggio di traccia è una funzione (o macro) aggiunta al codice per scrivere messaggi di traccia.

Scelta di una funzione del messaggio di traccia

  • La funzione messaggio di traccia predefinita è la macro DoTraceMessage . Se si usa la funzione predefinita, è possibile controllare quando generare messaggi usando i valori Trace Flag per il provider. I valori dei flag di Trace sono i flag definiti durante la creazione del GUID del controllo nel passaggio 1. Se si usa DoTraceMessage, le macro WPP predefinite sono già definite automaticamente (WPP_LEVEL_ENABLED e WPP_LEVEL_LOGGER), quindi è possibile ignorare il resto di questo passaggio e andare al passaggio 5.

  • Se si usa uno dei modelli KMDF o UMDF, la funzione TraceEvents e le macro WPP necessarie sono già definite per abilitare tale funzione, quindi è possibile passare al passaggio 5.

  • Se si sta creando una funzione di messaggio di traccia personalizzata o si sta convertendo la funzione di stampa di debug esistente, proseguire con il resto di questo passaggio.

Creazione o personalizzazione di una funzione del messaggio di traccia

  1. Se si usano funzioni di messaggio di traccia personalizzate o si desidera convertire funzioni di stampa di debug (ad esempio KdPrint) per generare messaggi di traccia, è necessario definire macro WPP che identificano e abilitano le funzioni del messaggio di traccia nel provider di traccia. Inserire queste macro nel file di intestazione Trace.h che hai aggiunto al progetto.

  2. Definire le macro WPP per abilitare la funzione di traccia.

    Ogni funzione del messaggio di traccia utilizzata deve avere una coppia di macro corrispondente. Queste macro identificano il provider di traccia e specificano le condizioni che generano i messaggi. In genere si definiscono una coppia di macro, WPP_<condizione>_LOGGER e WPP_<condizione>_ENABLED in termini di macro predefinite WPP_LEVEL_ENABLED e WPP_LEVEL_LOGGER.

Termine Description
WPP_CONDITIONS_LOGGER Utilizzato per trovare la sessione di traccia associata al provider e restituisce un handle alla sessione.
WPP_CONDITIONS_ENABLED Consente di determinare se la registrazione è abilitata con la condizione specificata.

Per le macro WPP definite, le CONDIZIONI rappresentano le condizioni supportate dalla funzione messaggio di traccia, nell'ordine in cui vengono visualizzate nell'elenco dei parametri della funzione, separate da caratteri di sottolineatura. Ad esempio, la funzione del messaggio di traccia predefinita DoTraceMessage supporta solo Trace Flag come condizione, quindi c'è solo un parametro nei nomi delle macro (WPP_LEVEL_ENABLED).

Annotazioni

Sfortunatamente, i nomi delle macro predefinite (WPP_LEVEL_ENABLED e WPP_LEVEL_LOGGER) sembrano indicare il parametro Del livello di traccia , ma fanno effettivamente riferimento al flag di traccia.

Se si usa una funzione messaggio di traccia personalizzata, è possibile impostare qualificatori aggiuntivi, ad esempio il livello di traccia. Il livello di traccia è definito nel file Evntrace.h e i livelli di traccia offrono un modo pratico per classificare i messaggi di traccia come messaggi di errore, avviso e informativo.

Ad esempio, è possibile aggiungere il frammento di codice seguente al file di intestazione aggiunto al progetto. Il codice seguente definisce le macro WPP personalizzate per una funzione del messaggio di traccia che supporta i parametri Trace Level e Trace Flag come condizioni per generare messaggi di traccia. La macro WPP_LEVEL_FLAGS_ENABLED restituisce TRUE se la registrazione è abilitata per il valore FLAGS specificato e il valore LEVEL abilitato è maggiore o uguale all'argomento di livello utilizzato nella chiamata di funzione del messaggio di traccia.

#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) \
           WPP_LEVEL_LOGGER(flags)

#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \
           (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl)

Successivamente, è necessario specificare le funzioni di traccia personalizzate nel blocco di configurazione WPP (begin_wpp configurazione e end_wpp) Ad esempio, se si usa il modello per progetti UMDF o driver KMDF in Visual Studio, il modello definisce le macro WPP per una funzione messaggio di traccia personalizzata denominata TraceEvents. La funzione macro TraceEvents usa il livello di traccia e il flag di traccia come condizioni per la generazione di messaggi. Se è stata definita la macro WPP_LEVEL_FLAGS_ENABLED nel file di intestazione Trace.h, è possibile aggiungere la definizione di macro seguente.

//
// This comment block is scanned by the trace preprocessor to define the 
// TraceEvents function.
//
// begin_wpp config
// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
// end_wpp
//

È anche possibile convertire le istruzioni di stampa di debug esistenti in istruzioni di traccia dei messaggi mediante l'aggiunta di una dichiarazione FUNC simile nel blocco di configurazione WPP. Nell'esempio seguente, ad esempio, viene aggiunto il codice per convertire le istruzioni KdPrint esistenti. La dichiarazione FUNC definisce anche globalmente KdPrint per utilizzare il livello di traccia specificato e i flag {LEVEL=TRACE_LEVEL_INFORMATION, FLAGS=TRACE_DRIVER}. Anziché inviare l'output al debugger, le istruzioni di stampa di debug vengono inviate al log di traccia.

//
// This comment block is scanned by the trace preprocessor to define the
// TraceEvents function and conversion for KdPrint. Note the double parentheses for the KdPrint message, for compatibility with the KdPrint function.
//
// begin_wpp config
// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
// FUNC KdPrint{LEVEL=TRACE_LEVEL_INFORMATION, FLAGS=TRACE_DRIVER}((MSG, ...));
// end_wpp
//

Annotazioni

Se si vuole convertire KdPrintEx in una funzione di messaggio di traccia, è necessario eseguire alcuni passaggi aggiuntivi. Rispetto a KdPrint, la funzione KdPrintEx accetta due argomenti aggiuntivi. Per convertire la funzione KdPrintEx , è necessario definire un WPP_DEFINE_BIT per ComponentID e definire macro personalizzate WPP_<condition>_LOGGER e WPP_<condition>_ENABLED . Il secondo parametro per KdPrintEx specifica il livello di è simile ai valori del livello di traccia , pertanto non è necessario ridefinirli necessariamente.


#define WPP_CONTROL_GUIDS                                              \
    WPP_DEFINE_CONTROL_GUID(\
    myDriverTraceGuid, (11C3AAE4, 0D88, 41b3, 43BD, AC38BF747E19), \    /* change GUID for your provider */
        WPP_DEFINE_BIT(MYDRIVER_ALL_INFO)        /* bit  0 = 0x00000001 */ \
        WPP_DEFINE_BIT(TRACE_DRIVER)             /* bit  1 = 0x00000002 */ \
        WPP_DEFINE_BIT(TRACE_DEVICE)             /* bit  2 = 0x00000004 */ \
        WPP_DEFINE_BIT(TRACE_QUEUE)              /* bit  3 = 0x00000008 */ \
        WPP_DEFINE_BIT(DPFLTR_IHVDRIVER_ID)      /* bit  4 = 0x00000010 */\         /* Added for the ComponentID param of KdPrintEx */
    )

#define WPP_Flags_LEVEL_LOGGER(Flags, level)                                  \
    WPP_LEVEL_LOGGER(Flags)

#define WPP_Flags_LEVEL_ENABLED(Flags, level)                                 \
    (WPP_LEVEL_ENABLED(Flags) && \
    WPP_CONTROL(WPP_BIT_ ## Flags).Level >= level)



//
// This comment block is scanned by the trace preprocessor to convert the KdPrintEx function.
// Note the double parentheses for the KdPrint message, for compatiblility with the KdPrintEx function.
//
// begin_wpp config
// FUNC KdPrintEx((Flags, LEVEL, MSG, ...));   
// end_wpp
//

Passaggio 3: Includere i file di intestazione di traccia associati (con estensione h e tmh) nei file di origine C o C++

Se hai definito il GUID di controllo e i flag di traccia per il driver in un file di intestazione (ad esempio, trace.h), è necessario includere il file di intestazione nei file di origine in cui inizializzerai e libererai WPP (Passaggio 4) o chiamerai le funzioni di messaggio di traccia.

Inoltre, è necessario aggiungere la direttiva #include per Il File di Intestazione del Messaggio di Traccia (.tmh). Quando si compila il driver o l'applicazione, il preprocessore WPP genera i file di intestazione del messaggio di traccia (tmh) per ogni file di origine che contiene funzioni di messaggio di traccia.

/* -- driver.c  - include the *.tmh file that is generated by WPP --*/

#include "trace.h"     /* file that defines WPP_CONFIG_GUIDS and trace flags */
#include "driver.tmh"  /* this file is auto-generated */

Passaggio 4: Aggiungere macro alle funzioni di callback appropriate per inizializzare e pulire WPP

Per inizializzare WPP all'ingresso del driver

  • Aggiungere la macro WPP_INIT_TRACING alla routine DriverEntry di un driver in modalità kernel o di un driver UMDF 2.0 o alla routine DLLMain di un driver in modalità utente (UMDF 1.x) o di un'applicazione.

Per pulire le risorse WPP quando si esce dal driver

  • Aggiungere la macro WPP_CLEANUP alla routine di scaricamento del driver (ad esempio DriverContextCleanup o DriverUnload) di un driver in modalità kernel o di un driver UMDF 2.0.

    Per un driver in modalità utente (UMDF 1.x) o un'applicazione, aggiungere la macro WPP_CLEANUP alla routine DLLMain .

    È anche necessario aggiungere la macro WPP_CLEANUP alla routine DriverEntry nel caso in cui DriverEntry non riesca. Ad esempio, se driverEntry ha esito negativo, la routine di scaricamento del driver non verrà chiamata. Vedere la chiamata a WdfDriverCreate nell'esempio seguente.

Esempio di driver in modalità kernel con WPP_INIT_TRACING e WPP_CLEANUP in DriverEntry


NTSTATUS
DriverEntry(
    _In_ PDRIVER_OBJECT  DriverObject,
    _In_ PUNICODE_STRING RegistryPath
    )
{  

          //  ... 

                //
    // Initialize WPP Tracing in DriverEntry
    //
    WPP_INIT_TRACING( DriverObject, RegistryPath );

                //  ...


 //
    // Create a framework driver object to represent our driver.
    //
    status = WdfDriverCreate(
        DriverObject,
        RegistryPath,
        &attributes, // Driver Object Attributes
        &config,          // Driver Config Info
        WDF_NO_HANDLE // hDriver
        );

    if (!NT_SUCCESS(status)) {

        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,
                "WdfDriverCreate failed with status 0x%x\n", status);
        //
        // Cleanup tracing here because DriverContextCleanup will not be called
        // as we have failed to create WDFDRIVER object itself.
        // Please note that if you return failure from DriverEntry after the
        // WDFDRIVER object is created successfully, you don't have to
        // call WPP cleanup because in those cases DriverContextCleanup
        // will be executed when the framework deletes the DriverObject.
        //
        WPP_CLEANUP(DriverObject);

    }

                return status;

}

Esempio di driver in modalità kernel che usa WPP_CLEANUP in DriverContextCleanup



VOID
DriverContextCleanup(
       PDRIVER_OBJECT DriverObject
       )
{
    // ...

    // Clean up WPP resources on unload
    //
    WPP_CLEANUP(DriverObject);

   // ...

}

Esempio per il driver UMDF 2.0 usando WPP_INIT_TRACING in DriverEntry


/
// Driver specific #defines in trace header file (trace.h)
//
#define MYDRIVER_TRACING_ID      L"Microsoft\\UMDF2.0\\UMDF2_0Driver1 V1.0"

 // Initialize WPP Tracing in the DriverEntry routine
 //
    WPP_INIT_TRACING( MYDRIVER_TRACING_ID );

Esempio dell'uso del driver UMDF 1.0 delle macro WPP_INIT_TRACING e WPP_CLEANUP in DLLMain

/
// Driver specific #defines in trace header file (for example, trace.h)
//
#define MYDRIVER_TRACING_ID      L"Microsoft\\UMDF1.X\\UMDF1_XDriver1"


//
// DLL Entry Point - UMDF 1.0 example in the source file where you implement the DLL exports.
// 

extern "C"
BOOL
WINAPI
DllMain(
    HINSTANCE hInstance,
    DWORD dwReason,
    LPVOID lpReserved
    )
{
    if (dwReason == DLL_PROCESS_ATTACH) {
        WPP_INIT_TRACING(MYDRIVER_TRACING_ID);              // Initialize WPP tracing

        g_hInstance = hInstance;
        DisableThreadLibraryCalls(hInstance);

    } else if (dwReason == DLL_PROCESS_DETACH) {
        WPP_CLEANUP();                                                                                                              // Deactivate and cleanup WPP tracing
    }

    return _AtlModule.DllMain(dwReason, lpReserved);
}

Passaggio 5: Instrumentare il codice driver per generare messaggi di traccia nei punti appropriati

È possibile usare qualsiasi funzione messaggio di traccia scelta, purché la funzione del messaggio di traccia, i flag di traccia e i livelli siano definiti in modo appropriato. La funzione messaggio di traccia predefinita è la macro DoTraceMessage . È possibile aggiungere questa macro al codice per scrivere messaggi nel file di log. Nella tabella seguente sono elencate alcune delle funzioni di messaggio di traccia predefinite e le funzioni di stampa di debug che è possibile usare per creare messaggi di traccia.

Funzioni del messaggio di traccia di esempio Quando utilizzare
DoTraceMessage Questa è la funzione del messaggio di traccia predefinita. Il vantaggio dell'uso di DoTraceMessage è che la funzione è già definita. È possibile utilizzare i flag di traccia specificati nella macro WPP_CONFIG_GUIDS. Lo svantaggio dell'uso di DoTraceMessage è che la funzione accetta solo un parametro condizionale, ovvero i flag di traccia. Se si desidera utilizzare i livelli di traccia, per registrare solo messaggi di errore o di avviso, è possibile utilizzare la macro DoDebugTrace oppure utilizzare TraceEvents, che usa sia flag di traccia che livelli di traccia.
TraceEvents Se si crea un driver usando modelli WDF in Visual Studio, si tratta della funzione di messaggio di traccia predefinita. Il vantaggio dell'uso di TraceEvents è che la funzione del messaggio di traccia, i flag di traccia e il livello di traccia sono già definiti per l'utente. Inoltre, i modelli includono anche la strumentazione che scrive i messaggi nel file di log all'ingresso e all'uscita della funzione.
KdPrint, KdPrintEx, DbgPrint, DbgPrintEx Il vantaggio dell'uso delle funzioni di stampa di debug è che non è necessario modificare le istruzioni di stampa di debug esistenti. È possibile passare facilmente dalla visualizzazione dei messaggi nel debugger alla registrazione dei messaggi di traccia in un file. Se la funzione del messaggio di traccia è stata personalizzata per includere una delle funzioni di stampa di debug, non è necessario eseguire altre operazioni. Quando si crea una sessione di traccia con Logman o Tracelog o un altro controller di traccia, è sufficiente specificare i flag e i livelli per il provider. Tutti i messaggi di debug che soddisfano le condizioni specificate vengono stampati nel registro.

Utilizzo delle istruzioni DoTraceMessage

  1. Aggiungere la macro DoTraceMessage al codice come si farebbe con una routine di stampa di debug. La macro DoTraceMessage accetta 3 parametri: il livello del flag (TraceFlagName), che definisce la condizione quando viene scritto il messaggio di traccia, la stringa Message e l'elenco di variabili facoltativo.

    DoTraceMessage(TraceFlagName, Message, [VariableList... ])
    

    Ad esempio, l'istruzione DoTraceMessage seguente scrive il nome della funzione che contiene l'istruzione DoTraceMessage quando il flag TRACE_DRIVER, come definito in WPP_CONTROL_GUIDS, viene abilitato per la sessione di traccia.

         DoTraceMessage( TRACE_DRIVER, "\nEntering %!FUNC!" );
    
    

    Nell'esempio viene usata una stringa predefinita per la funzione attualmente in esecuzione (%FUNC!). Per altre informazioni sulle stringhe di specifiche di formato definite da WPP, vedere Che cosa sono le stringhe di specifiche di formato esteso WPP?

  2. Per generare il messaggio di traccia, creare una sessione di traccia per il provider di traccia usando Logman o Tracelog e specificare un flag di traccia che imposta il flag di TRACE_DRIVER (bit 1, 0x2).

//
//  DoTraceMessage examples
// 

     ...

// writes the name of the function that contains the trace statement when the flag, TRACE_DRIVER (bit 1, 0x2), 
// as defined in WPP_CONTROL_GUIDS, is enabled for the trace session.

     DoTraceMessage( TRACE_DRIVER, "\nEntering %!FUNC!" );

     ...

// writes the name of the function, the line number, and the error code 

      DoTraceMessage(
            TRACE_DRIVER,
            "[%s] Failed at %d (error code= %d)\n",
            __FUNCTION__,
            __LINE__,
            dwLastError);

Uso delle istruzioni di TraceEvents

Se si usano i modelli di driver di Windows in Visual Studio, la macro TraceEvents viene definita nel file di intestazione Trace.h.

  1. Aggiungere la macro TraceEvents al codice come si fa con una routine di stampa per il debug. La macro TraceEvents accetta i parametri seguenti: il livello di traccia (Livello) e il flag di traccia (Flag), che definiscono la condizione quando viene scritto il messaggio di traccia, la stringa Message e l'elenco di variabili facoltativo.

    TraceEvents(Level, Flags, Message, [VariableList... ])
    

    Ad esempio, l'istruzione TraceEvents seguente scrive il nome della funzione che contiene l'istruzione TraceEvents quando vengono soddisfatte le condizioni specificate nei parametri Trace Level e Trace Flag. Il livello di traccia è un valore intero; qualsiasi elemento al di sotto o al di sotto del livello di traccia specificato per tale sessione di traccia verrà tracciato. Il TRACE_LEVEL_INFORMATION è definito in Evntrace.h e ha il valore 4. Il flag TRACE_DRIVER (bit 1, 0x2) viene definito in WPP_CONTROL_GUIDS. Se questo bit TRACE_DRIVER è impostato per la sessione di traccia e il livello di traccia è 4 o superiore, TraceEvents scrive il messaggio di traccia.

            TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
    
    

    Nell'esempio viene usata una stringa predefinita per la funzione attualmente in esecuzione (%FUNC!). Per altre informazioni sulle stringhe di specifiche di formato definite da WPP, vedere Che cosa sono le stringhe di specifiche di formato esteso WPP?

  2. Per generare il messaggio di traccia, creare una sessione di traccia per il provider di traccia usando Logman o Tracelog. Specificare un livello di traccia per TRACE_LEVEL_INFORMATION (4) o superiore e specificare un livello di traccia che imposta il bit TRACE_DRIVER (bit 1, 0x2).

//
//  TraceEvents examples
// 


    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");

//


    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,
                       "OSRUSBFX2 Driver Sample - Driver Framework Edition.\n");

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT,
                "Built %s %s\n", __DATE__, __TIME__);

Passaggio 6: Modificare il progetto di Visual Studio per eseguire il preprocessore WPP e compilare la soluzione

WdK fornisce supporto per il preprocessore WPP, in modo da poter eseguire il preprocessore usando Visual Studio e l'ambiente MSBuild.

Per eseguire il preprocessore WPP

  1. Selezionare e tenere premuto (o fare clic con il pulsante destro del mouse) sul progetto driver in Esplora soluzioni e selezionare Proprietà.
  2. Nella pagina delle proprietà del progetto selezionare Proprietà di configurazione e selezionare Traccia WPP.
  3. In Generale impostare l'opzione Esegui WPP su .
  4. In Riga di comando aggiungere eventuali opzioni aggiuntive per personalizzare il comportamento di traccia. Per informazioni su ciò che è possibile aggiungere, vedi Preprocessore WPP.
  5. Compilare il progetto o la soluzione per la configurazione e la piattaforma di destinazione. Vedere Compilazione di un driver con WDK.

Per informazioni sul processo di compilazione, vedere Attività TraceWPP e WDK e ambiente di compilazione di Visual Studio.

È anche possibile eseguire il preprocessore separato dall'ambiente di compilazione usando lo strumento TraceWPP (TraceWPP.exe). Questo strumento si trova nella sottodirectory bin/x86 e bin/x64 di WDK.

Passaggio 7: Avviare una sessione di traccia per acquisire e verificare i messaggi di traccia

Per verificare di aver configurato correttamente la traccia WPP, è necessario installare il driver o l'applicazione in un computer di test e quindi creare una sessione di traccia per acquisire i messaggi di traccia. È possibile creare una sessione di traccia per il provider di traccia usando qualsiasi controller di traccia, ad esempio Logman, Tracelog o TraceView. È possibile scrivere i messaggi in un file di log o inviarli a un debugger del kernel. A seconda delle funzioni del messaggio di traccia in uso, è necessario assicurarsi di specificare i flag di traccia e i livelli di traccia che genereranno i messaggi.

Ad esempio, se si usano i livelli di traccia definiti in Evntrace.h e si vuole acquisire TRACE_LEVEL_INFORMATION (4) o versione successiva, è necessario impostare il livello su 4. Quando si imposta il livello su 4 per la sessione di traccia, verranno acquisiti anche tutti i messaggi informativi (4), avviso (3), errore (2) e critico (1), presupponendo che vengano soddisfatte anche eventuali altre condizioni, ad esempio i flag di traccia.

Per verificare che tutti i messaggi vengano generati, è sufficiente impostare il livello di traccia e i flag di traccia su valori massimi in modo che vengano generati tutti i messaggi. I flag di traccia usano una maschera di bit (ULONG), quindi è possibile impostare tutti i bit (ad esempio, 0xFFFFFFFF). I livelli di traccia sono rappresentati da un valore di byte. Ad esempio, se si usa Logman, è possibile specificare 0xFF per coprire tutti i livelli.

(Esempio) Avvio di una sessione di traccia con Logman

logman create trace "myWPP_session" -p {11C3AAE4-0D88-41b3-43BD-AC38BF747E19} 0xffffffff 0xff -o c:\DriverTest\TraceFile.etl 

logman start "myWPP_session"

logman stop "myWPP_session"

(Esempio) Avvio di una sessione di traccia con TraceLog

tracelog -start MyTrace -guid  MyProvider.guid -f d:\traces\testtrace.etl -flag 2 -level 0xFFFF

Il comando Tracelog include il parametro -f per specificare il nome e il percorso del file di log di traccia eventi. Include il parametro -flag per specificare i flag impostati e il parametro -level per specificare l'impostazione del livello. È possibile omettere questi parametri, ma alcuni provider di traccia non generano messaggi di traccia a meno che non si imposti il flag o il livello. Il livello di traccia è definito nel file Evntrace.h e i livelli di traccia offrono un modo pratico per classificare i messaggi di traccia come messaggi critici, di errore, di avviso e informativi.