Condividi tramite


Aggiunta della traccia software WPP a un driver Windows

Per usare la traccia software WPP in un provider di traccia, ad esempio un driver in modalità kernel o un'applicazione in modalità utente, è necessario aggiungere codice (o strumento) ai file di origine del driver e modificare il progetto driver. Questa sezione descrive questi passaggi.

Mancia Il modo più semplice per aggiungere la traccia WPP al driver consiste nell'usare uno dei modelli di driver KMDF o UMDF in Visual Studio. Se si usano i modelli, gran parte del codice che è necessario aggiungere è già stata eseguita. In Visual Studio selezionare File > Nuovo > progetto e quindi selezionare il progetto WDF Windows Driver (modalità utente o modalità kernel). Le macro WPP sono definite nel file di intestazione Trace.h incluso nell'ambito 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 di controllo, un identificatore e flag di traccia. Questa operazione viene eseguita in modo che sia possibile identificare e controllare quando e cosa si vuole tracciare. Mentre 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. Il file di intestazione deve essere incluso (#include) in qualsiasi file di origine che si intende instrumentare per la traccia.

Per aggiungere WPP_CONTROL_GUIDS macro al driver:

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

  2. Aggiungere una macro WPP_CONTROL_GUIDS per specificare il nome descrittivo per il provider di traccia, definire un GUID di 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 i cinque campi, ma sono separati da virgole e parentesi quadre, anziché i trattini e le parentesi graffe consuete. Ad esempio, si specifica ((84bdb2e9,829e,41b3,b891,02f454bc2bd7) anziché {84bdb2e9-829e-41b3-b891-02f454bc2bd7 }.

    Esempio di un'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 */ \
            )                             
    

    Mancia È possibile copiare questo frammento di codice in un file di intestazione. Assicurarsi 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 > Create GUID). È anche possibile usare lo strumento Uuidgen.exe, disponibile dalla finestra del prompt dei comandi di Visual Studio (digitare uuidgen.exe /? per altre informazioni).

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

    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 per la generazione di messaggi di traccia. Nell'esempio WPP_CONTROL_GUIDS l'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. Si usano i flag di traccia quando si aggiungono funzioni di messaggio di traccia al codice sorgente (descritto nel passaggio 5: Instrumentare il codice driver per generare messaggi di traccia in punti appropriati).

    Nota 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. Aggiungere 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 che specificano che il flag di traccia viene scritto nel log.

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

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

Scelta di una funzione di messaggio di traccia

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

  2. 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.

  3. Se si crea una funzione di messaggio di traccia personalizzata o si converte la funzione di stampa di debug esistente, continuare con il resto di questo passaggio.

Creazione o personalizzazione di una funzione di messaggio di traccia

  1. Se si usano funzioni di messaggio di traccia personalizzate o si desidera convertire le 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 aggiunto al progetto.

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

    Ogni funzione del messaggio di traccia usata deve avere una coppia corrispondente di macro. 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_<condition>>_ENABLED in termini di macro predefinite WPP_LEVEL_ENABLED e WPP_LEVEL_LOGGER.<

Ogni funzione del messaggio di traccia usata deve avere una coppia corrispondente di macro. 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_<condition>>_ENABLED in termini di macro predefinite WPP_LEVEL_ENABLED e WPP_LEVEL_LOGGER.<

Termine Descrizione

WPP_CONDITIONS_LOGGER

Usato per trovare la sessione di traccia associata al provider e restituisce un handle alla sessione.

WPP_CONDITIONS_ENABLED

Usato per determinare se la registrazione è abilitata con la condizione specificata.

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

Nota Sfortunatamente, i nomi delle macro predefinite (WPP_LEVEL_ENABLED e WPP_LEVEL_LOGGER) sembrano indicare il parametro Di livello di traccia , ma in realtà fanno riferimento al flag di traccia.

Se si usa una funzione di 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 errori, avvisi e messaggi informativi.

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 di messaggio di traccia che supporta sia il livello di traccia che i parametri del flag di traccia 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 alla 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)

È quindi 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 di 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 aggiunta di una dichiarazione FUNC simile nel blocco di configurazione WPP. Ad esempio, nell'esempio seguente viene aggiunto il codice per convertire le istruzioni KdPrint esistenti. La dichiarazione FUNC definisce anche a livello globale KdPrint per usare il livello di traccia specificato e contrassegnare {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
//

Nota 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_condizione_LOGGER e WPP_<condizione>>_ENABLED.< Il secondo parametro per KdPrintEx specifica il livello di è simile ai valori di Livello di traccia , quindi non è necessariamente necessario ridefinirli.


#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 (.h e .tmh) nei file di origine C o C++

Se è stato definito il GUID del 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 inizializzare e scaricare funzioni WPP (Passaggio 4) o chiamare le funzioni del messaggio di traccia.

È inoltre necessario aggiungere un'istruzione #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 nella voce del driver

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

Per pulire le risorse WPP all'uscita del driver

  • Aggiungere la macro WPP_CLEANUP alla routine di scaricamento driver(ad esempio DriverContextCleanup o DriverUnload) di un driver in modalità kernel o 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 consigliabile aggiungere la macro WPP_CLEANUP alla routine DriverEntry nel caso in cui DriverEntry ha esito negativo. 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 usando 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 usando 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 per l'uso del driver UMDF 1.0 di 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 del driver per generare messaggi di traccia in punti appropriati

È possibile usare qualsiasi funzione di 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 di 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 Utilizzo
DoTraceMessage

Si tratta della funzione di messaggio di traccia predefinita. Il vantaggio di usare DoTraceMessage è che la funzione è già definita per l'utente. È possibile usare 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 usare i livelli di traccia, per registrare solo messaggi di errore o di avviso, è possibile usare la macro DoDebugTrace o usare TraceEvents, che usa sia flag di traccia che livelli di traccia.

TraceEvents

Se si crea un driver usando i modelli WDF in Visual Studio, si tratta della funzione di messaggio di traccia predefinita. Il vantaggio di usare 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 la strumentazione che scrive i messaggi nel file di log all'ingresso e all'uscita dalla funzione.

KdPrint, KdPrintEx, DbgPrint, DbgPrintEx

Il vantaggio di usare le 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 è stata personalizzata la funzione di messaggio di traccia per includere una delle funzioni di stampa di debug, non è necessario eseguire più 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. Tutte le istruzioni di stampa di debug che soddisfano le condizioni specificate vengono stampate nel log.

Uso di istruzioni DoTraceMessage

  1. Aggiungere la macro DoTraceMessage al codice come si vuole eseguire un debug di routine di stampa. La macro DoTraceMessage accetta 3 parametri: il livello di flag (TraceFlagName), che definisce la condizione quando il messaggio di traccia viene scritto, 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 di TRACE_DRIVER, come definito in WPP_CONTROL_GUIDS, è 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 specifica del formato definite da WPP, vedere Quali sono le stringhe di specifiche di formato estese 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);

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

Uso di istruzioni TraceEvents

  1. Aggiungere la macro TraceEvents al codice come una routine di stampa di 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 Messaggio e l'elenco di variabili facoltative.

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

    Ad esempio, l'istruzione TraceEvents seguente scrive il nome della funzione contenente l'istruzione TraceEvents quando vengono soddisfatte le condizioni specificate nei parametri Trace Level e Trace Flag. Il livello di traccia è un valore integer; qualsiasi elemento 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 specifica del formato definite da WPP, vedere Quali sono le stringhe di specifiche di formato estese 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 maggiore 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 che sia possibile 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 cosa è possibile aggiungere, vedere 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à TraceWPPe 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 del 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 avere i messaggi scritti in un file di log o inviati 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 maggiore, è necessario impostare il livello su 4. Quando si imposta il livello su 4 per la sessione di traccia, tutte le informazioni (4), l'avviso (3), l'errore (2) e i messaggi critici (1) verranno acquisiti, presupponendo che siano 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 tutti i messaggi vengano generati. 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 imposta 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, errori, avvisi e messaggi informativi.