다음을 통해 공유


Windows 드라이버에 WPP 소프트웨어 추적 추가

커널 모드 드라이버 또는 사용자 모드 애플리케이션과 같은 추적 공급자에서 WPP 소프트웨어 추적을 사용하려면 드라이버 원본 파일을 코드(또는 계측)하고 드라이버 프로젝트를 수정해야 합니다. 이 섹션에서는 이러한 단계를 설명합니다.

드라이버에 WPP 추적을 추가하는 가장 쉬운 방법은 Visual Studio에서 KMDF 또는 UMDF 드라이버 템플릿 중 하나를 사용하는 것입니다. 템플릿을 사용하는 경우 추가해야 하는 대부분의 코드가 이미 완료되었습니다. Visual Studio에서 파일 > 새 > 프로젝트를 선택한 다음 Windows 드라이버(사용자 모드 또는 커널 모드) WDF 프로젝트를 선택합니다. WPP 매크로는 프로젝트의 일부로 포함된 Trace.h 헤더 파일에 정의됩니다. 템플릿 중 하나를 사용하는 경우 5단계로 건너뛸 수 있습니다.

1단계: 컨트롤 GUID 및 추적 플래그 정의

모든 추적 공급자(예: 드라이버 또는 사용자 모드 앱)는 고유하게 정의되어야 합니다. 이렇게 하려면 컨트롤 GUID, 식별자 및 추적 플래그를 정의하는 WPP_CONTROL_GUIDS 매크로를 추가합니다. 추적할 시기와 내용을 식별하고 제어할 수 있도록 수행됩니다. 각 드라이버에는 일반적으로 별도의 컨트롤 GUID가 있지만 드라이버에는 여러 컨트롤 GUID가 있거나 여러 드라이버가 하나의 컨트롤 GUID를 공유할 수 있습니다.

편의를 위해 WPP_CONTROL_GUIDS 매크로는 일반적으로 공통 헤더 파일에 정의됩니다. 헤더 파일은 추적을 위해 계측하려는 원본 파일에 포함되어야 합니다(#include).

드라이버에 WPP_CONTROL_GUIDS 매크로를 추가하려면 다음을 수행합니다.

  1. WPP 추적 매크로를 정의하는 데 사용할 수 있는 새 C++ 헤더 파일을 Visual Studio 프로젝트에 추가합니다. 예를 들어 솔루션 탐색기 드라이버를 길게 누르거나 마우스 오른쪽 단추로 클릭하고 새 항목 추가 > 를 선택합니다. 파일을 저장합니다(예: Trace.h).

  2. WPP_CONTROL_GUIDS 매크로를 추가하여 추적 공급자의 이름을 지정하고, 컨트롤 GUID를 정의하고, 특정 추적 메시지를 한정하는 데 사용할 수 있는 추적 플래그를 정의합니다.

    WPP_CONTROL_GUIDS 매크로에는 다음 구문이 있습니다.

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

    예를 들어 다음 코드는 myDriverTraceGuid를 GUIDFriendlyName으로 사용합니다. ControlGUID의 형식은 32자리 16진수 GUID의 표준 형식과 약간 다릅니다. ControlGUID에는 5개의 필드가 있지만 일반적인 하이픈과 중괄호 대신 쉼표로 구분되고 괄호로 괄호로 묶습니다. 예를 들어 {84bdb2e9-829e-02f454bc2bd7} 대신 ((84bdb2e9,829e,41b3,829e,41b3,829e,41b3,b891,41b3,b891,b891,02f454bc2bd7 } 대신 (84bdb2e9,829e,02f454bc2bd7)을 지정합니다.

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

    이 코드 조각을 헤더 파일에 복사할 수 있습니다. 컨트롤 GUID 및 식별 이름을 변경해야 합니다. GUIDgen.exe 사용하여 컨트롤 GUID를 생성할 수 있습니다. Guidgen.exe Visual Studio(도구 > GUID 만들기)에 포함되어 있습니다. Visual Studio 명령 프롬프트 창에서 사용할 수 있는 Uuidgen.exe 도구를 사용할 수도 있습니다(자세한 내용은 /?uuidgen.exe 입력).

  3. 추적 공급자에 대한 추적 플래그 를 정의합니다.

    WPP_CONTROL_GUIDS 매크로의 WPP_DEFINE_BIT 요소는 추적 공급자에 대한 추적 플래그를 정의합니다. 일반적으로 플래그는 점점 더 자세한 보고 수준을 나타내지만 추적 메시지를 생성하기 위한 조건으로 원하는 방식으로 플래그를 사용할 수 있습니다. WPP_CONTROL_GUIDS 예제에서 WPP_DEFINE_BIT 네 개의 추적 플래그(MYDRIVER_ALL_INFO, TRACE_DRIVER, TRACE_DEVICE 및 TRACE_QUEUE)를 정의합니다.

    최대 31개까지 추적 플래그를 정의할 수 있습니다. WPP는 나타나는 순서대로 요소에 비트 값을 할당합니다(예: 비트 0(0x1), 비트 1(0x2), 비트 2(0x4), 비트 3(0x8) 등) 소스 코드에 추적 메시지 함수를 추가할 때 추적 플래그를 사용합니다( 5단계: 적절한 지점에서 추적 메시지를 생성하도록 드라이버 코드 계측에 설명됨).

    참고 추적 플래그를 사용하여 특정 구성 요소(예: 특정 I/O 요청 또는 디바이스 또는 드라이버 개체의 활동)를 추적할 시기를 제어할 수 있습니다. 추적 메시지 문(예 DoTraceMessage (TRACE_DRIVER, "Hello World!\n"): )에 추적 플래그를 추가합니다. Tracelog와 같은 추적 컨트롤러를 사용하여 추적 세션을 만들 때 해당 세션의 추적 공급자에 사용할 -flag 옵션을 지정합니다. 이 경우 플래그는 TRACE_DRIVER 플래그에 해당하는 비트 1(0x1)입니다. 추적 세션을 시작하면 추적 플래그를 지정하는 모든 추적 메시지가 로그에 기록됩니다.

2단계: 사용하려는 추적 메시지 함수를 선택하고 해당 함수에 대한 WPP 매크로를 정의합니다.

디버그 인쇄 함수와 마찬가지로 추적 메시지 함수는 코드에 추가하여 추적 메시지를 작성하는 함수(또는 매크로)입니다.

추적 메시지 함수 선택

  1. 기본 추적 메시지 함수는 DoTraceMessage 매크로입니다. 기본 함수를 사용하는 경우 공급자에 대한 추적 플래그 값을 사용하여 메시지를 생성할 시기를 제어할 수 있습니다. 추적 플래그 값은 1단계에서 컨트롤 GUID를 만들 때 정의한 플래그입니다. DoTraceMessage를 사용하는 경우 기본 WPP 매크로가 이미 정의되어 있으므로(WPP_LEVEL_ENABLED 및 WPP_LEVEL_LOGGER) 이 단계의 나머지 부분을 건너뛰고 5단계로 이동합니다.

  2. KMDF 또는 UMDF 템플릿 중 하나를 사용하는 경우 TraceEvents 함수와 해당 함수를 사용하도록 설정하는 데 필요한 WPP 매크로가 이미 정의되어 있으므로 5단계로 건너뛸 수 있습니다.

  3. 고유한 추적 메시지 함수를 만들거나 기존 디버그 인쇄 함수를 변환하는 경우 이 단계의 나머지 부분을 계속 진행합니다.

추적 메시지 함수 만들기 또는 사용자 지정

  1. 사용자 지정 추적 메시지 함수를 사용하거나 디버그 인쇄 함수(예: KdPrint)를 변환하여 추적 메시지를 생성하려는 경우 추적 공급자에서 추적 메시지 함수를 식별하고 사용하도록 설정하는 WPP 매크로를 정의해야 합니다. 프로젝트에 추가한 Trace.h 헤더 파일에 이러한 매크로를 넣습니다.

  2. 추적 함수를 사용하도록 WPP 매크로를 정의합니다.

    사용하는 각 추적 메시지 함수에는 해당 매크로 쌍이 있어야 합니다. 이러한 매크로는 추적 공급자를 식별하고 메시지를 생성하는 조건을 지정합니다. 일반적으로 기본 WPP_LEVEL_ENABLED 및 WPP_LEVEL_LOGGER 매크로의 관점에서 매크로, WPP_<조건>_LOGGERWPP_<조건>_ENABLED 쌍을 정의합니다.

사용하는 각 추적 메시지 함수에는 해당 매크로 쌍이 있어야 합니다. 이러한 매크로는 추적 공급자를 식별하고 메시지를 생성하는 조건을 지정합니다. 일반적으로 기본 WPP_LEVEL_ENABLED 및 WPP_LEVEL_LOGGER 매크로의 관점에서 매크로, WPP_<조건>_LOGGERWPP_<조건>_ENABLED 쌍을 정의합니다.

용어 Description

WPP_조건_LOGGER

공급자와 연결된 추적 세션을 찾고 세션에 대한 핸들을 반환하는 데 사용됩니다.

WPP_조건_ENABLED

지정된 조건에서 로깅을 사용할 수 있는지 여부를 확인하는 데 사용됩니다.

정의하는 WPP 매크로의 경우 CONDITIONS 는 추적 메시지 함수가 지원하는 조건을 함수의 매개 변수 목록에 나타나는 순서대로 밑줄로 구분하여 나타냅니다. 예를 들어 기본 추적 메시지 함수인 DoTraceMessage추적 플래그 만 조건으로 지원하므로 매크로 이름(WPP_LEVEL_ENABLED)에 매개 변수가 하나만 있습니다.

참고 아쉽게도 기본 매크로(WPP_LEVEL_ENABLED 및 WPP_LEVEL_LOGGER)의 이름은 추적 수준 매개 변수를 나타내는 것처럼 보이지만 실제로는 추적 플래그를 참조합니다.

사용자 지정 추적 메시지 함수를 사용하는 경우 추적 수준과 같은 추가 한정자를 설정할 수 있습니다. 추적 수준은 Evntrace.h 파일에 정의되며 추적 수준은 추적 메시지를 오류, 경고 및 정보 메시지로 분류하는 편리한 방법을 제공합니다.

예를 들어 프로젝트에 추가한 헤더 파일에 다음 코드 조각을 추가할 수 있습니다. 다음 코드는 추적 수준 및 추적 플래그 매개 변수를 모두 지원하는 추적 메시지 함수에 대한 사용자 지정 WPP 매크로를 추적 메시지를 생성하는 조건으로 정의합니다. 지정된 FLAGS 값에 대해 로깅을 사용하도록 설정하고 활성화된 LEVEL 값이 추적 메시지 함수 호출에 사용된 level 인수보다 크거나 같은 경우 WPP_LEVEL_FLAGS_ENABLED 매크로는 TRUE를 반환합니다.

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

다음으로 WPP 구성 블록(begin_wpp 구성end_wpp)에서 사용자 지정 추적 함수를 지정해야 합니다. 예를 들어 Visual Studio에서 UMDF 또는 KMDF 드라이버 프로젝트에 템플릿을 사용하는 경우 템플릿은 TraceEvents라는 사용자 지정 추적 메시지 함수에 대한 WPP 매크로를 정의합니다. TraceEvents 매크로 함수는 추적 수준 및 추적 플래그를 메시지 생성 조건으로 사용합니다. Trace.h 헤더 파일에서 WPP_LEVEL_FLAGS_ENABLED 매크로를 정의한 경우 다음 매크로 정의를 추가할 수 있습니다.

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

WPP 구성 블록에 유사한 FUNC 선언을 추가하여 기존 디버그 인쇄 문을 추적 메시지 문으로 변환할 수도 있습니다. 예를 들어 다음 예제에서는 기존 KdPrint 문을 변환하는 코드를 추가합니다. FUNC 선언은 지정된 추적 수준을 사용하고 {LEVEL=TRACE_LEVEL_INFORMATION, FLAGS=TRACE_DRIVER}에 플래그를 지정하도록 KdPrint를 전역적으로 정의합니다. 디버거에 출력을 보내는 대신 디버그 인쇄 문이 추적 로그로 전송됩니다.

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

참고KdPrintEx 를 추적 메시지 함수로 변환하려면 몇 가지 추가 단계를 수행해야 합니다. KdPrint에 비해 KdPrintEx 함수는 두 개의 추가 인수를 사용합니다. KdPrintEx 함수를 변환하려면 ComponentID에 대한 WPP_DEFINE_BIT 정의하고 사용자 지정 WPP_<조건>_LOGGERWPP_<조건>_ENABLED 매크로를 정의해야 합니다. KdPrintEx의 두 번째 매개 변수는 의 수준이 추적 수준 값과 유사하도록 지정하므로 반드시 재정의할 필요는 없습니다.


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

3단계: C 또는 C++ 원본 파일에 연결된 추적 헤더 파일(.h 및 .tmh)을 포함합니다.

헤더 파일(예: trace.h)에서 드라이버에 대한 컨트롤 GUID 및 추적 플래그를 정의한 경우 WPP(4단계)를 초기화 및 언로드하거나 추적 메시지 함수를 호출할 원본 파일에 헤더 파일을 포함해야 합니다.

또한 추적 메시지 헤더 파일(.tmh)에 대한 #include 문을 추가해야 합니다. 드라이버 또는 애플리케이션을 빌드할 때 WPP 전처리기는 추적 메시지 함수를 포함하는 각 원본 파일에 대한 추적 메시지 헤더 파일(.tmh)을 생성합니다.

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

4단계: 적절한 콜백 함수에 매크로를 추가하여 WPP를 초기화하고 클린

드라이버 항목에서 WPP를 초기화하려면

  • 널 모드 드라이버 또는 UMDF 2.0 드라이버의 DriverEntry 루틴 또는 사용자 모드 드라이버(UMDF 1.x) 또는 애플리케이션의 DLLMain 루틴에 WPP_INIT_TRACING 매크로를 추가합니다.

드라이버 종료에서 WPP 리소스를 클린

  • 널 모드 드라이버 또는 UMDF 2.0 드라이버의 드라이버 언로드 루틴(예: DriverContextCleanup 또는 DriverUnload)에 WPP_CLEANUP 매크로를 추가합니다.

    사용자 모드 드라이버(UMDF 1.x) 또는 애플리케이션의 경우 WPP_CLEANUP 매크로를 DLLMain 루틴에 추가합니다.

    또한 DriverEntry가 실패할 경우 driverEntry 루틴에 WPP_CLEANUP 매크로를 추가해야 합니다. 예를 들어 DriverEntry 가 실패하면 드라이버 언로드 루틴이 호출되지 않습니다. 다음 예제에서는 WdfDriverCreate 호출을 참조하세요.

DriverEntry에서 WPP_INIT_TRACING 및 WPP_CLEANUP 사용하는 커널 모드 드라이버의 예


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;

}

DriverContextCleanup에서 WPP_CLEANUP 사용하는 커널 모드 드라이버의 예



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

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

   // ...

}

DriverEntry에서 WPP_INIT_TRACING 사용하는 UMDF 2.0 드라이버의 예


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

DLLMain에서 WPP_INIT_TRACING 및 WPP_CLEANUP 매크로의 UMDF 1.0 드라이버 사용 예제

/
// 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);
}

5단계: 적절한 지점에서 추적 메시지를 생성하도록 드라이버 코드 계측

추적 메시지 함수, 추적 플래그 및 수준이 적절하게 정의된 경우 선택한 추적 메시지 함수를 사용할 수 있습니다. 기본 추적 메시지 함수는 DoTraceMessage 매크로입니다. 이 매크로를 코드에 추가하여 로그 파일에 메시지를 쓸 수 있습니다. 다음 표에는 미리 정의된 추적 메시지 함수 및 추적 메시지를 만드는 데 사용할 수 있는 디버그 인쇄 함수가 나와 있습니다.

예제 추적 메시지 함수 사용 시기
DoTraceMessage

기본 추적 메시지 함수입니다. DoTraceMessage를 사용할 경우의 이점은 함수가 이미 정의되어 있다는 것입니다. WPP_CONFIG_GUIDS 매크로에서 지정한 추적 플래그를 사용할 수 있습니다. DoTraceMessage를 사용하는 단점은 함수가 조건부 매개 변수, 즉 추적 플래그를 하나만 사용한다는 것입니다. 추적 수준을 사용하거나 오류 또는 경고 메시지만 기록하려면 DoDebugTrace 매크로를 사용하거나 추적 플래그와 추적 수준을 모두 사용하는 TraceEvents를 사용할 수 있습니다.

TraceEvents

Visual Studio에서 WDF 템플릿을 사용하여 드라이버를 만드는 경우 기본 추적 메시지 함수입니다. TraceEvents를 사용할 경우의 이점은 추적 메시지 함수, 추적 플래그 및 추적 수준이 이미 정의되어 있다는 것입니다. 또한 템플릿에는 함수 입력 및 종료 시 로그 파일에 메시지를 쓰는 계측도 포함됩니다.

KdPrint, KdPrintEx, DbgPrint, DbgPrintEx

디버그 인쇄 함수를 사용할 경우의 이점은 기존 디버그 인쇄 문을 수정할 필요가 없다는 것입니다. 디버거에서 메시지 보기에서 파일의 추적 메시지 기록으로 쉽게 전환할 수 있습니다. 디버그 인쇄 함수 중 하나를 포함하도록 추적 메시지 함수를 사용자 지정한 경우 더 이상 작업을 수행할 필요가 없습니다. Logman 또는 Tracelog 또는 다른 추적 컨트롤러를 사용하여 추적 세션을 만들 때 공급자의 플래그와 수준을 지정하기만 하면 됩니다. 지정한 조건을 충족하는 모든 디버그 인쇄 문은 로그에 인쇄됩니다.

DoTraceMessage 문 사용

  1. 디버그 인쇄 루틴처럼 DoTraceMessage 매크로를 코드에 추가합니다. DoTraceMessage 매크로는 추적 메시지를 쓸 때 조건, 메시지 문자열 및 선택적 변수 목록을 정의하는 플래그 수준(TraceFlagName)의 세 가지 매개 변수를 사용합니다.

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

    예를 들어 다음 DoTraceMessage 문은 WPP_CONTROL_GUIDS 정의된 TRACE_DRIVER 플래그가 추적 세션에 대해 사용하도록 설정된 경우 DoTraceMessage 문이 포함된 함수의 이름을 씁니다.

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

    이 예제에서는 현재 실행 중인 함수(%FUNC!)의 에 대해 미리 정의된 문자열을 사용합니다. WPP 정의 형식 사양 문자열에 대한 자세한 내용은 WPP 확장 형식 사양 문자열이란?을 참조하세요.

  2. 추적 메시지를 생성하려면 Logman 또는 Tracelog를 사용하여 추적 공급자에 대한 추적 세션을 만들고 TRACE_DRIVER 플래그(비트 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);

Visual Studio에서 Windows 드라이버 템플릿을 사용하는 경우 Trace.h 헤더 파일에서 TraceEvents 매크로가 정의됩니다.

TraceEvents 문 사용

  1. 디버그 인쇄 루틴처럼 TraceEvents 매크로를 코드에 추가합니다. TraceEvents 매크로는 추적 수준(수준) 및 추적 플래그(Flags)와 같은 매개 변수를 사용합니다. 이 매개 변수는 추적 메시지를 쓸 때 조건, 메시지 문자열 및 선택적 변수 목록을 정의합니다.

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

    예를 들어 다음 TraceEvents 문은 추적 수준 및 추적 플래그 매개 변수에 지정된 조건이 충족될 때 TraceEvents 문을 포함하는 함수의 이름을 씁니다. 추적 수준은 정수 값입니다. 해당 추적 세션에 대해 지정된 추적 수준 이하의 모든 항목이 추적됩니다. TRACE_LEVEL_INFORMATION Evntrace.h에 정의되며 값은 4입니다. TRACE_DRIVER 플래그(비트 1, 0x2)는 WPP_CONTROL_GUIDS 정의됩니다. 추적 세션에 대해 이 TRACE_DRIVER 비트가 설정되고 추적 수준이 4 이상인 경우 TraceEvents 는 추적 메시지를 씁니다.

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

    이 예제에서는 현재 실행 중인 함수(%FUNC!)의 에 대해 미리 정의된 문자열을 사용합니다. WPP 정의 형식 사양 문자열에 대한 자세한 내용은 WPP 확장 형식 사양 문자열이란?을 참조하세요.

  2. 추적 메시지를 생성하려면 Logman 또는 Tracelog를 사용하여 추적 공급자에 대한 추적 세션을 만듭니다. 추적 수준을 TRACE_LEVEL_INFORMATION(4) 이상으로 지정하고 TRACE_DRIVER 비트(비트 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__);

6단계: WPP 전처리기를 실행하고 솔루션을 빌드하도록 Visual Studio 프로젝트 수정

WDK는 Visual Studio 및 MSBuild 환경을 사용하여 전처리기를 실행할 수 있도록 WPP 전처리기를 지원합니다.

WPP 전처리기를 실행하려면

  1. 솔루션 Explorer 드라이버 프로젝트를 길게 누르거나 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다.
  2. 프로젝트 속성 페이지에서 구성 속성을 선택하고 WPP 추적을 선택합니다.
  3. 일반에서 WPP 실행 옵션을 예로 설정합니다.
  4. 명령줄에서 추적 동작을 사용자 지정하는 추가 옵션을 추가합니다. 추가할 수 있는 항목에 대한 자세한 내용은 WPP 전처리기를 참조하세요.
  5. 대상 구성 및 플랫폼에 대한 프로젝트 또는 솔루션을 빌드합니다. WDK를 사용하여 드라이버 빌드를 참조하세요.

빌드 프로세스에 대한 자세한 내용은 TraceWPP 작업WDK 및 Visual Studio 빌드 환경을 참조하세요.

TraceWPP 도구(TraceWPP.exe)를 사용하여 빌드 환경과 별도로 전처리기를 실행할 수도 있습니다. 이 도구는 WDK의 bin/x86 및 bin/x64 하위 디렉터리에 있습니다.

7단계: 추적 메시지를 캡처하고 확인하는 추적 세션 시작

WPP 추적을 올바르게 설정했는지 확인하려면 테스트 컴퓨터에 드라이버 또는 애플리케이션을 설치한 다음 추적 메시지를 캡처하는 추적 세션을 만들어야 합니다. Logman, Tracelog 또는 TraceView와 같은 추적 컨트롤러를 사용하여 추적 공급자에 대한 추적 세션을 만들 수 있습니다. 메시지가 로그 파일에 기록되거나 커널 디버거로 전송될 수 있습니다. 사용 중인 추적 메시지 함수에 따라 메시지를 생성할 추적 플래그 및 추적 수준을 지정해야 합니다.

예를 들어 Evntrace.h에 정의된 추적 수준을 사용하고 TRACE_LEVEL_INFORMATION(4) 이상을 캡처하려는 경우 수준을 4로 설정해야 합니다. 추적 세션에 대해 수준을 4로 설정하면 추적 플래그와 같은 다른 조건도 충족되는 경우 모든 정보(4), 경고(3), 오류(2) 및 중요(1) 메시지도 캡처됩니다.

모든 메시지가 생성되었는지 확인하려면 추적 수준 및 추적 플래그를 최대 값으로 설정하여 모든 메시지가 생성되도록 할 수 있습니다. 추적 플래그는 ULONG(비트 마스크)을 사용하므로 모든 비트(예: 0xFFFFFFFF)를 설정할 수 있습니다. 추적 수준은 바이트 값으로 표시됩니다. 예를 들어 Logman을 사용하는 경우 모든 수준의 0xFF 지정할 수 있습니다.

(예) 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"

(예) TraceLog를 사용하여 추적 세션 시작

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

Tracelog 명령에는 이벤트 추적 로그 파일의 이름과 위치를 지정하는 -f 매개 변수가 포함됩니다. 여기에는 플래그 집합을 지정하는 -flag 매개 변수와 수준 설정을 지정하는 -level 매개 변수가 포함됩니다. 이러한 매개 변수를 생략할 수 있지만 플래그 또는 수준을 설정하지 않는 한 일부 추적 공급자는 추적 메시지를 생성하지 않습니다. 추적 수준은 Evntrace.h 파일에 정의되며 추적 수준은 추적 메시지를 중요, 오류, 경고 및 정보 메시지로 분류하는 편리한 방법을 제공합니다.