Udostępnij przez


Dodawanie funkcji śledzenia oprogramowania WPP do sterownika systemu Windows

Aby użyć funkcji śledzenia oprogramowania WPP u dostawcy śledzenia, takiego jak sterownik trybu jądra lub aplikacja trybu użytkownika, należy dodać kod (lub instrument) pliki źródłowe sterownika i zmodyfikować projekt sterownika. W tej sekcji opisano te kroki.

Uwaga / Notatka

Najprostszym sposobem dodania śledzenia WPP do sterownika jest użycie jednego z szablonów sterowników KMDF lub UMDF w programie Visual Studio. Jeśli używasz szablonów, znaczna część kodu, który musisz dodać, jest już wykonana za Ciebie. W programie Visual Studio wybierz pozycję Plik > Nowy > Projekt, a następnie wybierz projekt WDF sterownika systemu Windows (tryb użytkownika, lub tryb jądra). Makra programu WPP są definiowane w pliku nagłówkowym Trace.h, który jest zawarty w ramach projektu. Jeśli używasz jednego z szablonów, możesz przejść do kroku 5.

Krok 1: Definiuj kontrolny identyfikator GUID i flagi śledzenia

Każdy dostawca śledzenia (taki jak sterownik lub aplikacja w trybie użytkownika) musi być jednoznacznie zdefiniowany. Należy to zrobić, dodając makro WPP_CONTROL_GUIDS, które definiuje GUID kontrolki, identyfikator oraz flagi śledzenia. Dzięki temu można identyfikować i kontrolować, kiedy i co chcesz śledzić. Chociaż każdy sterownik zazwyczaj ma oddzielny identyfikator GUID kontrolki, sterownik może mieć wiele identyfikatorów GUID sterowania lub wiele sterowników może współużytkować jeden identyfikator GUID kontrolki.

Dla wygody makro WPP_CONTROL_GUIDS jest zwykle definiowane w typowym pliku nagłówka. Plik nagłówka musi być uwzględniony (#include) w dowolnym pliku źródłowym, który ma zostać instrumentowany do śledzenia.

Aby dodać makro WPP_CONTROL_GUIDS do sterownika:

  1. Dodaj nowy plik nagłówka języka C++ do projektu programu Visual Studio, którego można użyć do definiowania makr śledzenia programu WPP. Na przykład wybierz i przytrzymaj (lub kliknij prawym przyciskiem myszy) sterownik w Eksploratorze rozwiązań, a następnie wybierz pozycję Dodaj > nowy element. Zapisz plik (na przykład jako Trace.h).

  2. Dodaj makro WPP_CONTROL_GUIDS, aby określić przyjazną nazwę dla dostawcy śledzenia, zdefiniować kontrolny identyfikator GUID i zdefiniować flagi śledzenia, których można użyć do kwalifikacji określonych komunikatów śledzenia.

    Makro WPP_CONTROL_GUIDS ma następującą składnię:

    Składnia dla 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) \
            )
    

    Na przykład poniższy kod używa myDriverTraceGuid jako GUIDFriendlyName. Należy pamiętać, że ControlGUID ma nieco inny format niż standardowa forma 32-znakowego szesnastkowego identyfikatora GUID. Kontrolka ControlGUID ma pięć pól, ale są oddzielone przecinkami i nawiasami, zamiast zwykłych łączników i nawiasów klamrowych. Na przykład należy określić wartość ((84bdb2e9,829e,41b3,b891,02f454bc2bd7) zamiast {84bdb2e9-829e-41b3-b891-02f454bc2bd7}.

    Przykład instrukcji 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 */ \
            )                             
    

    Uwaga / Notatka

    Ten fragment kodu można skopiować do pliku nagłówka. Pamiętaj, aby zmienić identyfikator GUID (unikalny kod identyfikacyjny) kontrolki i przyjazną nazwę. Możesz użyć GUIDgen.exe do wygenerowania identyfikatora GUID kontrolki. Ten Guidgen.exe jest dostępny w pakiecie z programem Visual Studio (Narzędzia > Tworzenie identyfikatora GUID). Możesz również użyć narzędzia Uuidgen.exe, które jest dostępne w oknie wiersza polecenia programu Visual Studio (wpisz uuidgen.exe /? aby uzyskać więcej informacji).

  3. Zdefiniuj flagi śledzenia dla dostawcy.

    Elementy WPP_DEFINE_BIT makra WPP_CONTROL_GUIDS określają flagi śledzenia dla dostawcy śledzenia. Zazwyczaj flagi reprezentują coraz bardziej szczegółowe poziomy raportowania, ale można używać flag jako dowolnych sposobów generowania komunikatów śledzenia. W przykładzie WPP_CONTROL_GUIDS WPP_DEFINE_BIT definiuje cztery flagi śledzenia (MYDRIVER_ALL_INFO, TRACE_DRIVER, TRACE_DEVICE i TRACE_QUEUE).

    Można zdefiniować maksymalnie 31 flag śledzenia. Program WPP przypisuje wartości bitowe do elementów w kolejności ich wyświetlania, na przykład bit 0 (0x1), bit 1 (0x2), bit 2 (0x4), bit 3 (0x8) itd. Flagi śledzenia są używane podczas dodawania funkcji komunikatów śledzenia do kodu źródłowego (opisanego w kroku 5: Instrumentacja kodu sterownika w celu generowania komunikatów śledzenia w odpowiednich punktach).

    Uwaga / Notatka

    Za pomocą flag śledzenia można kontrolować, kiedy śledzić określone składniki (na przykład określone żądania we/wy lub działania obiektów urządzenia lub sterownika). Dodajesz flagę śledzenia do instrukcji komunikatu śledzenia (na przykład DoTraceMessage (TRACE_DRIVER, "Hello World!\n")). Podczas tworzenia sesji śledzenia za pomocą kontrolera śledzenia, takiego jak Tracelog, należy określić opcję -flaga do użycia dla dostawcy śledzenia w tej sesji, w tym przypadku flaga jest bitem 1 (0x1), która odpowiada flagi TRACE_DRIVER. Po rozpoczęciu sesji śledzenia wszystkie komunikaty śledzenia, które oznaczają tę flagę śledzenia, są zapisywane w dzienniku.

Krok 2. Wybierz funkcje komunikatów śledzenia, które zamierzasz używać, i zdefiniuj makra WPP dla tych funkcji.

Podobnie jak funkcja drukowania komunikatów debugowania, funkcja komunikatów śledzenia jest funkcją (lub makrem) dodaną do kodu w celu pisania komunikatów śledzenia.

Wybieranie funkcji komunikatu śledzenia

  • Domyślną funkcją komunikatu śledzenia jest makro DoTraceMessage . Jeśli używasz funkcji domyślnej, możesz kontrolować, kiedy generować komunikaty, używając wartości Trace Flag dla twojego dostawcy. Wartości flag śledzenia to flagi zdefiniowane podczas tworzenia identyfikatora GUID kontrolki w kroku 1. Jeśli używasz DoTraceMessage, domyślne makra WPP są już zdefiniowane (WPP_LEVEL_ENABLED i WPP_LEVEL_LOGGER), dlatego możesz pominąć resztę tego kroku i przejść do kroku 5.

  • Jeśli używasz jednego z szablonów KMDF lub UMDF, funkcja TraceEvents i niezbędne makra WPP są już zdefiniowane w celu włączenia tej funkcji, dzięki czemu można przejść do kroku 5.

  • Jeśli tworzysz własną funkcję komunikatu śledzenia lub konwertujesz istniejącą funkcję drukowania debugowania, przejdź do dalszej części tego kroku.

Tworzenie lub dostosowywanie funkcji komunikatu śledzenia

  1. Jeśli używasz niestandardowych funkcji komunikatów śledzenia lub chcesz przekonwertować funkcje drukowania debugowania (na przykład KdPrint) na generowanie komunikatów śledzenia, musisz zdefiniować makra programu WPP identyfikujące i obsługujące funkcje komunikatów śledzenia u dostawcy śledzenia. Umieść te makra w pliku nagłówkowym Trace.h dodanym do projektu.

  2. Zdefiniuj makra programu WPP, aby włączyć funkcję śledzenia.

    Każda używana funkcja komunikatu śledzenia musi mieć odpowiednią parę makr. Te makra identyfikują dostawcę śledzenia i określają warunki, które generują komunikaty. Zazwyczaj definiuje się parę makr, WPP_<condition>_LOGGER i WPP_<condition>_ENABLED pod względem domyślnych makr WPP_LEVEL_ENABLED i WPP_LEVEL_LOGGER.

Termin Opis
WPP_CONDITIONS_LOGGER Służy do znajdowania sesji śledzenia skojarzonej z dostawcą i zwraca dojście do sesji.
WPP_CONDITIONS_ENABLED Służy do określania, czy rejestrowanie jest włączone z określonym warunkiem.

W przypadku zdefiniowanych makr WPP warunki reprezentują warunki obsługiwane przez funkcję komunikatu śledzenia, w kolejności, w której są wyświetlane na liście parametrów funkcji, oddzielone podkreśleniami. Na przykład domyślna funkcja komunikatu śledzenia , DoTraceMessage, obsługuje tylko flagę śledzenia jako warunek, więc istnieje tylko jeden parametr w nazwach makr (WPP_LEVEL_ENABLED).

Uwaga / Notatka

Niestety, nazwy makr domyślnych (WPP_LEVEL_ENABLED i WPP_LEVEL_LOGGER) wydają się wskazywać parametr Poziom śledzenia , ale rzeczywiście odwołują się do flagi śledzenia.

Jeśli używasz niestandardowej funkcji komunikatu śledzenia, możesz ustawić dodatkowe kwalifikatory, takie jak poziom śledzenia. Poziom śledzenia jest definiowany w pliku Evntrace.h, a poziomy śledzenia zapewniają wygodny sposób klasyfikowania komunikatów śledzenia jako komunikatów o błędach, ostrzeżeniach i komunikatach informacyjnych.

Możesz na przykład dodać następujący fragment kodu do pliku nagłówka dodanego do projektu. Poniższy kod definiuje niestandardowe makra programu WPP dla funkcji komunikatu śledzenia, która obsługuje zarówno parametry poziom śledzenia, jak i flagę śledzenia jako warunki do generowania komunikatów śledzenia. Makro WPP_LEVEL_FLAGS_ENABLED zwraca wartość TRUE, jeśli rejestrowanie jest włączone dla wskazanej wartości FLAGS, a włączona wartość LEVEL jest większa lub równa argumentowi poziomu użytemu podczas wywołania funkcji śledzenia komunikatu.

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

Następnie należy określić niestandardowe funkcje śledzenia w bloku konfiguracji programu WPP (begin_wpp config i end_wpp). Na przykład, jeśli używasz szablonu dla projektów sterowników UMDF lub KMDF w programie Visual Studio, szablon definiuje makra programu WPP dla niestandardowej funkcji komunikatu śledzenia o nazwie TraceEvents. Funkcja makr TraceEvents używa wartości Trace Level i Trace Flag jako warunków generowania komunikatów. Jeśli zdefiniowano makro WPP_LEVEL_FLAGS_ENABLED w pliku nagłówka Trace.h, możesz dodać następującą definicję makra.

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

Możesz również przekonwertować istniejące komunikaty debugowania na instrukcje komunikatów śledzenia, dodając podobną deklarację FUNC w bloku konfiguracji WPP. Na przykład poniższy przykład dodaje kod, aby przekonwertować istniejące instrukcje KdPrint . Deklaracja FUNC również globalnie definiuje KdPrint do używania określonego poziomu śledzenia i flagi {LEVEL=TRACE_LEVEL_INFORMATION, FLAGS=TRACE_DRIVER}. Zamiast wysyłać dane wyjściowe do debugera, komunikaty diagnostyczne są wysyłane do dziennika logowania.

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

Uwaga / Notatka

Jeśli chcesz przekonwertować element KdPrintEx na funkcję komunikatu śledzenia, musisz wykonać kilka dodatkowych kroków. W porównaniu z funkcją KdPrintEx funkcja KdPrintEx przyjmuje dwa dodatkowe argumenty. Aby przekonwertować funkcję KdPrintEx, należy zdefiniować WPP_DEFINE_BIT dla ComponentID i zdefiniować niestandardowe WPP_<condition>_LOGGER oraz WPP_<condition>_ENABLED makra. Drugi parametr KdPrintEx określa poziom, który jest podobny do poziomów śledzenia, więc nie trzeba ich ponownie definiować.


#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
//

Krok 3. Dołącz skojarzone pliki nagłówka śledzenia (h i tmh) do plików źródłowych C lub C++

Jeśli zdefiniowano identyfikator GUID kontrolki i flagi śledzenia dla sterownika w pliku nagłówka (na przykład trace.h), należy dołączyć plik nagłówka do plików źródłowych, w których zainicjujesz i zwolnisz funkcję WPP (krok 4) lub wywołaj funkcje komunikatów śledzenia.

Ponadto należy dodać instrukcję #include dla pliku nagłówka wiadomości śledzenia (tmh). Podczas kompilowania sterownika lub aplikacji preprocesor WPP generuje pliki nagłówka komunikatów śledzenia (tmh) dla każdego pliku źródłowego zawierającego funkcje komunikatów śledzenia.

/* -- 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 */

Krok 4. Dodawanie makr do odpowiednich funkcji wywołania zwrotnego w celu zainicjowania i wyczyszczenia programu WPP

Aby zainicjować program WPP podczas wprowadzania sterownika

  • Dodaj makro WPP_INIT_TRACING do procedury DriverEntry sterownika trybu jądra lub sterownika UMDF 2.0 lub do procedury DLLMain sterownika trybu użytkownika (UMDF 1.x) lub aplikacji.

Aby wyczyścić zasoby programu WPP podczas zamykania sterownika

  • Dodaj makro WPP_CLEANUP do procedury zwalniania sterownika (na przykład DriverContextCleanup lub DriverUnload) sterownika trybu jądra lub sterownika UMDF 2.0.

    W przypadku sterownika trybu użytkownika (UMDF 1.x) lub aplikacji dodaj makro WPP_CLEANUP do procedury DLLMain .

    Należy również dodać makro WPP_CLEANUP do procedury DriverEntry w przypadku niepowodzenia driverEntry . Jeśli na przykład driverEntry ulegnie awarii, procedura zwalniania sterownika nie zostanie wywołana. Zobacz wywołanie usługi WdfDriverUtwórz w poniższym przykładzie.

Przykład sterownika trybu jądra używającego WPP_INIT_TRACING i WPP_CLEANUP w 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;

}

Przykład sterownika w trybie jądra używającego WPP_CLEANUP w DriverContextCleanup



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

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

   // ...

}

Przykładowy sterownik UMDF 2.0 korzystający z WPP_INIT_TRACING w 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 );

Przykład użycia w sterowniku UMDF 1.0 makr WPP_INIT_TRACING i WPP_CLEANUP w funkcji 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);
}

Krok 5. Instrumentacja kodu sterownika w celu generowania komunikatów śledzenia w odpowiednich punktach

Możesz użyć dowolnej wybranej funkcji komunikatu śledzenia, pod warunkiem, że funkcja komunikatu śledzenia, flagi śledzenia i poziomy są odpowiednio zdefiniowane. Domyślną funkcją komunikatu śledzenia jest makro DoTraceMessage . To makro można dodać do kodu, aby zapisywać komunikaty w pliku dziennika. W poniższej tabeli wymieniono niektóre wstępnie zdefiniowane funkcje komunikatów śledzenia i funkcje drukowania debugowania, których można użyć do tworzenia komunikatów śledzenia.

Przykładowe funkcje komunikatów śledzenia Kiedy należy używać
DoTraceMessage Jest to domyślna funkcja komunikatu śledzenia. Zaletą korzystania z funkcji DoTraceMessage jest to, że funkcja jest już zdefiniowana. Możesz użyć flag śledzenia, które określisz w makrze WPP_CONFIG_GUIDS. Wadą korzystania z funkcji DoTraceMessage jest to, że funkcja przyjmuje tylko jeden parametr warunkowy, czyli flagi śledzenia. Jeśli chcesz użyć poziomów śledzenia, aby rejestrować tylko komunikaty o błędach lub ostrzeżeniach, możesz użyć makra DoDebugTrace lub użyć traceEvents, które używają zarówno flag śledzenia, jak i poziomów śledzenia.
TraceEvents Jeśli tworzysz sterownik przy użyciu szablonów usługi WDF w programie Visual Studio, jest to domyślna funkcja komunikatu śledzenia. Zaletą korzystania z funkcji TraceEvents jest to, że funkcja komunikatu śledzenia, flagi śledzenia i poziom śledzenia są już zdefiniowane. Ponadto szablony obejmują również instrumentację, która zapisuje komunikaty w pliku dziennika podczas wprowadzania funkcji i zamykania.
KdPrint, KdPrintEx, DbgPrint, DbgPrintEx Zaletą korzystania z funkcji debugowania jest to, że nie trzeba modyfikować istniejących instrukcji. Możesz łatwo przełączyć się z wyświetlania komunikatów w debugerze do rejestrowania komunikatów śledzenia w pliku. Jeśli funkcja komunikatu śledzenia została dostosowana tak, aby zawierała jedną z funkcji drukowania debugowania, nie trzeba wykonywać więcej pracy. Podczas tworzenia sesji śledzenia za pomocą narzędzia Logman lub Tracelog lub innego kontrolera śledzenia wystarczy określić flagi i poziomy dla dostawcy. Wszystkie komunikaty debugowania spełniające określone warunki są zapisywane w dzienniku.

Używanie instrukcji DoTraceMessage

  1. Dodaj makro DoTraceMessage do kodu, tak jak dodawałbyś rutynę debugowania. Makro DoTraceMessage przyjmuje 3 parametry: poziom flagi (TraceFlagName), który definiuje warunek podczas zapisywania komunikatu śledzenia, ciągu komunikatu i opcjonalnej listy zmiennych.

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

    Na przykład następująca instrukcja DoTraceMessage zapisuje nazwę funkcji, która zawiera instrukcję DoTraceMessage , gdy flaga TRACE_DRIVER zdefiniowana w WPP_CONTROL_GUIDS jest włączona dla sesji śledzenia.

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

    W przykładzie użyto wstępnie zdefiniowanego ciągu dla aktualnie wykonywanej funkcji (%FUNC!). Aby uzyskać więcej informacji na temat ciągów specyfikacji formatu zdefiniowanego przez WPP, zobacz Jakie są ciągi specyfikacji rozszerzonego formatu WPP?

  2. Aby wygenerować komunikat śledzenia, utwórz sesję śledzenia dla dostawcy śledzenia przy użyciu narzędzia Logman lub Tracelog i określ flagę śledzenia ustawiającą flagę 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);

Używanie instrukcji TraceEvents

Jeśli używasz szablonów sterowników systemu Windows w programie Visual Studio, makro TraceEvents jest zdefiniowane dla Ciebie w pliku nagłówka Trace.h.

  1. Dodaj makro TraceEvents do kodu, tak jak w przypadku procedury drukowania debugowania. Makro TraceEvents przyjmuje następujące parametry: poziom śledzenia (poziom) i flagę śledzenia (Flagi), która definiuje warunek podczas zapisywania komunikatu śledzenia, ciągu komunikatu i opcjonalnej listy zmiennych.

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

    Na przykład następująca instrukcja TraceEvents zapisuje nazwę funkcji, która zawiera instrukcję TraceEvents , gdy warunki określone w parametrach Poziom śledzenia i Flaga śledzenia są spełnione. Poziom śledzenia jest wartością całkowitą; wszystkie elementy z lub poniżej poziomu śledzenia określone dla tej sesji śledzenia zostaną prześledzonych. TRACE_LEVEL_INFORMATION jest definiowana w pliku Evntrace.h i ma wartość 4. Flaga TRACE_DRIVER (bit 1, 0x2) jest definiowana w WPP_CONTROL_GUIDS. Jeśli ten TRACE_DRIVER bit jest ustawiony dla sesji śledzenia, a poziom śledzenia wynosi 4 lub więcej, traceEvents zapisuje komunikat śledzenia.

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

    W przykładzie użyto wstępnie zdefiniowanego ciągu dla aktualnie wykonywanej funkcji (%FUNC!). Aby uzyskać więcej informacji na temat ciągów specyfikacji formatu zdefiniowanego przez WPP, zobacz Jakie są ciągi specyfikacji rozszerzonego formatu WPP?

  2. Aby wygenerować komunikat śledzenia, utwórz sesję śledzenia dla dostawcy śledzenia przy użyciu narzędzia Logman lub Tracelog. Określ poziom śledzenia TRACE_LEVEL_INFORMATION (4) lub nowszy i określ poziom śledzenia, który ustawia 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__);

Krok 6. Modyfikowanie projektu programu Visual Studio w celu uruchomienia preprocesora programu WPP i skompilowania rozwiązania

Zestaw WDK zapewnia obsługę preprocesora WPP, dzięki czemu można uruchomić preprocesor przy użyciu programu Visual Studio i środowiska MSBuild.

Aby uruchomić preprocesor programu WPP

  1. Wybierz i przytrzymaj (lub kliknij prawym przyciskiem myszy) projekt sterownika w Eksploratorze rozwiązań i wybierz pozycję Właściwości.
  2. Na stronie właściwości projektu wybierz pozycję Właściwości konfiguracji i wybierz pozycję Śledzenie programu WPP.
  3. W obszarze Ogólne ustaw opcję Uruchom program WPP na Wartość Tak.
  4. W obszarze Wiersz polecenia dodaj wszelkie dodatkowe opcje, aby dostosować zachowanie śledzenia. Aby uzyskać informacje na temat tego, co można dodać, zobacz Preprocesor WPP.
  5. Skompiluj projekt lub rozwiązanie dla docelowej konfiguracji i platformy. Zobacz Tworzenie sterownika za pomocą zestawu WDK.

Aby uzyskać informacje o procesie kompilacji, zobacz TraceWPP task and WDK and Visual Studio build environment (Środowisko kompilacji TraceWPP i WDK i Visual Studio).

Można również uruchomić preprocesor oddzielony od środowiska kompilacji przy użyciu narzędzia TraceWPP (TraceWPP.exe). To narzędzie znajduje się w podkatalogu bin/x86 i bin/x64 zestawu WDK.

Krok 7. Rozpocznij sesję śledzenia w celu przechwycenia i zweryfikowania komunikatów śledzenia

Aby sprawdzić, czy śledzenie WPP zostało skonfigurowane poprawnie, należy zainstalować sterownik lub aplikację na komputerze testowym, a następnie utworzyć sesję śledzenia w celu przechwycenia komunikatów śledzenia. Możesz utworzyć sesję śledzenia dla dostawcy śledzenia przy użyciu dowolnego kontrolera śledzenia, takiego jak Logman, Tracelog lub TraceView. Komunikaty mogą być zapisywane w pliku dziennika lub wysyłane do debugera jądra. W zależności od używanych funkcji komunikatów śledzenia należy określić flagi śledzenia i poziomy śledzenia, które będą generować komunikaty.

Jeśli na przykład używasz poziomów śledzenia zdefiniowanych w pliku Evntrace.h i chcesz przechwycić TRACE_LEVEL_INFORMATION (4) lub nowsze, musisz ustawić poziom na 4. Po ustawieniu poziomu 4 dla sesji śledzenia wszystkie informacje informacyjne (4), ostrzeżenie (3), błąd (2) i komunikaty krytyczne (1) również zostaną przechwycone, przy założeniu, że wszystkie inne warunki, takie jak flagi śledzenia, również zostaną spełnione.

Aby sprawdzić, czy wszystkie komunikaty są generowane, możesz po prostu ustawić poziom śledzenia i flagi śledzenia na maksymalne wartości, aby wszystkie komunikaty zostały wygenerowane. Flagi śledzenia używają maski bitowej (ULONG), więc można ustawić wszystkie bity (na przykład 0xFFFFFFFF). Poziomy śledzenia są reprezentowane przez wartość bajtu. Jeśli na przykład używasz narzędzia Logman, możesz określić wartość 0xFF, aby objąć wszystkie poziomy.

(Przykład) Uruchamianie sesji śledzenia przy użyciu narzędzia 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"

(Przykład) Uruchamianie sesji śledzenia przy użyciu usługi TraceLog

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

Polecenie Tracelog zawiera parametr -f , aby określić nazwę i lokalizację pliku dziennika śledzenia zdarzeń. Zawiera parametr -flag , aby określić ustawione flagi i parametr -level , aby określić ustawienie poziomu. Można pominąć te parametry, ale niektórzy dostawcy śledzenia nie generują żadnych komunikatów śledzenia, chyba że ustawisz flagę lub poziom. Poziom śledzenia jest zdefiniowany w pliku Evntrace.h, a poziomy śledzenia zapewniają wygodny sposób klasyfikowania komunikatów śledzenia jako komunikatów krytycznych, błędów, ostrzeżeń i komunikatów informacyjnych.