Kernel-Mode 드라이버에 이벤트 추적 추가

이 섹션에서는 ETW(Windows용 이벤트 추적) 커널 모드 API를 사용하여 커널 모드 드라이버에 이벤트 추적을 추가하는 방법을 설명합니다. ETW 커널 모드 API는 Windows Vista에서 도입되었으며 이전 운영 체제에서는 지원되지 않습니다. 드라이버가 Windows 2000 이상에서 추적 기능을 지원해야 하는 경우 WPP 소프트웨어 추적 또는 WMI 이벤트 추적 을 사용합니다.

WDK(Windows 드라이버 키트) 및 Visual Studio를 사용하여 ETW를 구현하는 방법을 보여 주는 샘플 코드를 보려면 Eventdrv 샘플을 참조하세요.

이 섹션에서는 다음 작업을 수행합니다.

워크플로 - Kernel-Mode 드라이버에 이벤트 추적 추가

1. 발생할 이벤트 유형 및 게시 위치 결정

2. 공급자, 이벤트 및 채널을 정의하는 계측 매니페스트 만들기

3. 메시지 컴파일러를 사용하여 계측 매니페스트 컴파일(Mc.exe)

4. 생성된 코드를 추가하여 이벤트를 발생(게시)합니다(등록, 등록 취소 및 이벤트 작성).

5. 드라이버 빌드

6. 매니페스트 설치

7. 드라이버를 테스트하여 ETW 지원 확인

워크플로 - Kernel-Mode 드라이버에 이벤트 추적 추가

커널 모드 드라이버에 이벤트 추적을 추가하는 프로세스를 보여 주는 순서도입니다.

1. 발생할 이벤트 유형 및 게시 위치 결정

코딩을 시작하기 전에 드라이버가 ETW(Windows용 이벤트 추적)를 통해 로그할 이벤트 유형을 결정해야 합니다. 예를 들어 드라이버가 배포된 후 문제를 진단하는 데 도움이 되는 이벤트 또는 드라이버를 개발할 때 도움이 될 수 있는 이벤트를 기록할 수 있습니다. 자세한 내용은 Windows 이벤트 로그 참조를 참조하세요.

이벤트 유형은 채널로 식별됩니다. 채널은 텔레비전 채널과 유사한 특정 대상을 대상으로 하는 관리, 운영, 분석 또는 디버그 유형의 명명된 이벤트 스트림입니다. 채널은 이벤트 공급자의 이벤트를 이벤트 로그 및 이벤트 소비자에게 전달합니다. 자세한 내용은 채널 정의를 참조하세요.

개발하는 동안 코드를 디버그하는 데 도움이 되는 이벤트를 추적하는 데 관심이 있습니다. 이 동일한 채널을 프로덕션 코드에서 사용하여 드라이버가 배포된 후 나타날 수 있는 문제를 해결할 수 있습니다. 성능을 측정하는 데 사용할 수 있는 이벤트를 추적할 수도 있습니다. 이러한 이벤트는 IT 전문가가 서버 성능을 미세 조정하는 데 도움이 되며 네트워크 병목 상태를 식별하는 데 도움이 될 수 있습니다.

2. 공급자, 이벤트 및 채널을 정의하는 계측 매니페스트 만들기

계측 매니페스트는 공급자가 발생시킬 이벤트에 대한 공식적인 설명을 제공하는 XML 파일입니다. 계측 매니페스트는 이벤트 공급자를 식별하고, 채널 또는 채널(최대 8개)을 지정하고, 이벤트를 설명하고, 이벤트가 사용하는 템플릿을 설명합니다. 또한 계측 매니페스트는 문자열 지역화를 허용하므로 추적 메시지를 지역화할 수 있습니다. 이벤트 시스템 및 이벤트 소비자는 매니페스트에 제공된 구조적 XML 데이터를 사용하여 쿼리 및 분석을 수행할 수 있습니다.

계측 매니페스트에 대한 자세한 내용은 계측 매니페스트 작성(Windows), EventManifest 스키마(Windows)Windows 이벤트 로그 사용(Windows)을 참조하세요.

다음 계측 매니페스트는 "샘플 드라이버"라는 이름을 사용하는 이벤트 공급자를 보여줍니다. 이 이름은 드라이버 이진 파일의 이름과 같을 필요는 없습니다. 또한 매니페스트는 공급자에 대한 GUID와 메시지 및 리소스 파일의 경로를 지정합니다. 메시지 및 리소스 파일을 통해 ETW는 이벤트를 디코딩하고 보고하는 데 필요한 리소스를 찾을 수 있는 위치를 알 수 있습니다. 이러한 경로는 드라이버(.sys) 파일의 위치를 가리킵니다. 대상 컴퓨터의 지정된 디렉터리에 드라이버를 설치해야 합니다.

이 예제에서는 관리 형식의 이벤트에 대한 채널인 명명된 채널 시스템을 사용합니다. 이 채널은 %WindowsSdkDir%\include\um 디렉터리에 WDK(Windows 드라이버 키트)와 함께 제공되는 Winmeta.xml 파일에 정의됩니다. 시스템 채널은 시스템 서비스 계정에서 실행되는 애플리케이션으로 보호됩니다. 매니페스트에는 이벤트가 게시될 때 이벤트와 함께 제공되는 데이터 형식과 정적 및 동적 콘텐츠를 설명하는 이벤트 템플릿이 포함됩니다. 이 예제 매니페스트는 , SampleEventAUnloadEvent의 세 가지 StartEvent이벤트를 정의합니다.

채널 외에도 이벤트를 수준 및 키워드와 연결할 수 있습니다. 키워드 및 수준은 이벤트를 사용하도록 설정하고 이벤트가 게시될 때 이벤트를 필터링하는 메커니즘을 제공하는 방법을 제공합니다. 키워드를 사용하여 논리적으로 관련된 이벤트를 함께 그룹화할 수 있습니다. 수준을 사용하여 이벤트의 심각도 또는 세부 정보(예: 위험, 오류, 경고 또는 정보)를 나타낼 수 있습니다. Winmeta.xml 파일에는 이벤트 특성에 대해 미리 정의된 값이 포함되어 있습니다.

이벤트 페이로드(이벤트 메시지 및 데이터)에 대한 템플릿을 만들 때는 입력 및 출력 형식을 지정해야 합니다. 지원되는 형식은 InputType 복합 형식(Windows)의 설명 섹션에 설명되어 있습니다.

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

3. 메시지 컴파일러를 사용하여 계측 매니페스트 컴파일(Mc.exe)

소스 코드를 컴파일하기 전에 메시지 컴파일러(Mc.exe) 를 실행해야 합니다. 메시지 컴파일러는 WDK(Windows 드라이버 키트)에 포함되어 있습니다. 메시지 컴파일러는 이벤트 공급자, 이벤트 특성, 채널 및 이벤트에 대한 정의를 포함하는 헤더 파일을 만듭니다. 소스 코드에 이 헤더 파일을 포함해야 합니다. 또한 메시지 컴파일러는 생성된 리소스 컴파일러 스크립트(*.rc) 및 리소스 컴파일러 스크립트에 포함된 생성된 .bin 파일(이진 리소스)을 배치합니다.

다음 몇 가지 방법으로 빌드 프로세스의 일부로 이 단계를 포함할 수 있습니다.

  • Eventdrv 샘플에 표시된 것처럼 드라이버 프로젝트 파일에 메시지 컴파일러 작업을 추가합니다.

  • Visual Studio를 사용하여 계측 매니페스트를 추가하고 메시지 컴파일러 속성을 구성합니다.

프로젝트 파일에 메시지 컴파일러 작업 추가 빌드 프로세스에 메시지 컴파일러를 포함할 수 있는 방법에 대한 예제는 Eventdrv 샘플에 대한 프로젝트 파일을 참조하세요. Eventdrv.vcxproj 파일에는 메시지 컴파일러를 <호출하는 MessageCompile> 섹션이 있습니다. 메시지 컴파일러는 매니페스트 파일(evntdrv.xml)을 입력으로 사용하여 헤더 파일 evntdrvEvents.h를 생성합니다. 또한 이 섹션에서는 생성된 RC 파일의 경로를 지정하고 커널 모드 로깅 매크로를 사용하도록 설정합니다. 이 섹션을 복사하여 드라이버 프로젝트 파일(.vcxproj)에 추가할 수 있습니다.


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

Eventdrv.sys 샘플을 빌드할 때 Visual Studio는 이벤트 추적에 필요한 파일을 만듭니다. 또한 드라이버 프로젝트의 리소스 파일 목록에 evntdrv.xml 매니페스트를 추가합니다. 매니페스트를 선택하고 길게 누르거나 마우스 오른쪽 단추로 클릭하여 메시지 컴파일러 속성 페이지를 볼 수 있습니다.

Visual Studio를 사용하여 계측 매니페스트 추가

드라이버 프로젝트에 계측 매니페스트를 추가한 다음 메시지 컴파일러 속성을 구성하여 필요한 리소스 및 헤더 파일을 빌드할 수 있습니다.

Visual Studio를 사용하여 프로젝트에 계측 매니페스트를 추가하려면

  1. 솔루션 탐색기 드라이버 프로젝트에 매니페스트 파일을 추가합니다. 리소스 파일 > 기존 항목 추가 > (예: evntdrv.xml 또는 mydriver.man)를 선택하고 길게 누르거나 마우스 오른쪽 단추로 클릭합니다.

  2. 방금 추가한 파일을 길게 누르거나 마우스 오른쪽 단추로 클릭하고 속성 페이지를 사용하여 항목 유형을 MessageCompile 로 변경하고 적용을 선택합니다.

  3. 메시지 컴파일러 속성이 나타납니다. 일반 설정에서 다음 옵션을 설정한 다음 적용을 선택합니다.

    일반 설정
    커널 모드 로깅 매크로 생성 예(-km)
    입력의 기본 이름 사용 예(-b)
  4. 파일 옵션에서 다음 옵션을 설정한 다음, 적용을 선택합니다.

    파일 옵션 설정
    카운터를 포함하기 위한 헤더 파일 생성
    헤더 파일 경로 $(IntDir)
    생성된 RC 및 이진 메시지 파일 경로
    RC 파일 경로 $(IntDir)
    생성된 파일 기본 이름 $(Filename)

기본적으로 메시지 컴파일러는 입력 파일의 기본 이름을 생성하는 파일의 기본 이름으로 사용합니다. 기본 이름을 지정하려면 생성된 파일 기본 이름 (-z) 필드를 설정합니다. Eventdr.sys 샘플에서 기본 이름은 evntdrv.c에 포함된 헤더 파일 evntdrvEvents.h 의 이름과 일치하도록 evntdrvEvents로 설정됩니다.

참고

Visual Studio 프로젝트에 생성된 .rc 파일을 포함하지 않으면 매니페스트 파일을 설치할 때 리소스에 대한 오류 메시지를 찾을 수 없습니다.

4. 생성된 코드를 추가하여 이벤트를 발생(게시) (등록, 등록 취소 및 쓰기 이벤트)

계측 매니페스트에서 이벤트 공급자 및 이벤트 설명자의 이름을 정의했습니다. 메시지 컴파일러를 사용하여 계측 매니페스트를 컴파일하면 메시지 컴파일러는 리소스를 설명하는 헤더 파일을 생성하고 이벤트에 대한 매크로도 정의합니다. 이제 이러한 이벤트를 발생하려면 생성된 코드를 드라이버에 추가해야 합니다.

  1. 원본 파일에 메시지 컴파일러(MC.exe)에서 생성된 이벤트 헤더 파일을 포함합니다. 예를 들어 Eventdrv 샘플에서 Evntdrv.c 소스 파일에는 이전 단계에서 생성된 헤더 파일(evntdrvEvents.h)이 포함됩니다.

    #include "evntdrvEvents.h"  
    
  2. 드라이버를 등록 및 등록 취소하는 매크로를 이벤트 공급자로 추가합니다. 예를 들어 Eventdrv 샘플 (evntdrvEvents.h)의 헤더 파일에서 메시지 컴파일러는 공급자의 이름을 기반으로 매크로를 만듭니다. 매니페스트에서 Eventdrv 샘플 은 "샘플 드라이버"라는 이름을 공급자의 이름으로 사용합니다. 메시지 컴파일러는 공급자의 이름을 이벤트 매크로와 결합하여 공급자를 등록합니다.이 경우 EventRegisterSample_Driver.

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

    DriverEntry 함수에 EventRegister<공급자> 매크로를 추가합니다. 디바이스 개체를 만들고 초기화하는 코드 다음에 이 함수를 추가합니다. EventRegister 공급자 함수에 대한 호출과 EventUnregister<><공급자> 호출을 일치시켜야 합니다. 드라이버의 언로드* 루틴에서 드라이버의 등록을 취소할 수 있습니다.

       // DriverEntry function
       // ...
    
    
        // Register with ETW
        //
        EventRegisterSample_Driver();
    
  3. 생성된 코드를 드라이버의 원본 파일에 추가하여 매니페스트에 지정한 이벤트를 작성(발생)합니다. 매니페스트에서 컴파일한 헤더 파일에는 드라이버에 대해 생성된 코드가 포함됩니다. 헤더 파일에 정의된 EventWrite<이벤트> 함수를 사용하여 추적 메시지를 ETW에 게시합니다. 예를 들어 다음 코드는 Eventdrv 샘플에 대해 evntdrvEvents.h에 정의된 이벤트에 대한 매크로를 보여 줍니다.

    이러한 이벤트를 작성하는 매크로를 , 및 EventWriteSampleEventAEventWriteUnloadEvent라고 합니다EventWriteStartEvent. 이러한 매크로 정의에서 볼 수 있듯이 매크로 정의에는 이벤트가 사용되는지 확인하는 EventEnabled<이벤트> 매크로가 자동으로 포함됩니다. 검사 이벤트가 활성화되지 않은 경우 페이로드를 빌드할 필요가 없습니다.

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

    발생 중인 이벤트에> 대한 소스 코드에 EventWrite< 이벤트 매크로를 추가합니다. 예를 들어 다음 코드 조각은 Eventdrv 샘플DriverEntry 루틴을 보여 줍니다. DriverEntry에는 ETW(EventRegisterSample_Driver)에 드라이버를 등록하는 매크로와 드라이버 이벤트를 ETW에 쓰는 매크로(EventWriteStartEvent)가 포함됩니다.

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

발생 중인 이벤트에 대한 모든 EventWrite<이벤트> 매크로를 소스 코드에 추가합니다. Eventdrv 샘플을 검사하여 드라이버 소스 코드의 이벤트에 대해 다른 두 매크로를 호출하는 방법을 확인할 수 있습니다.

  1. 생성된 헤더 파일에서 EventUnregister< 공급자 매크로를 사용하여 드라이버를 이벤트공급자>로 등록 취소합니다.

    드라이버 언로드 루틴에 이 함수 호출을 배치합니다. EventUnregister<공급자> 매크로가 호출된 후에는 추적 호출을 하지 않아야 합니다. 이벤트 공급자의 등록을 취소하지 않으면 프로세스와 연결된 콜백 함수가 더 이상 유효하지 않으므로 프로세스가 언로드될 때 오류가 발생할 수 있습니다.

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

5. 드라이버 빌드

계측 매니페스트를 프로젝트에 추가하고 메시지 컴파일러(MC.exe) 속성을 구성한 경우 Visual Studio 및 MSBuild를 사용하여 드라이버 프로젝트 또는 솔루션을 빌드할 수 있습니다.

  1. Visual Studio에서 드라이버 솔루션을 엽니다.

  2. 빌드 솔루션 빌드를 선택하여 빌드 메뉴에서 샘플을 빌드합니다. 솔루션 빌드에 대한 자세한 내용은 드라이버 빌드를 참조하세요.

6. 매니페스트 설치

이벤트 소비자(예: 이벤트 로그)가 이벤트 메타데이터를 포함하는 이진 파일의 위치를 찾을 수 있도록 대상 시스템에 매니페스트를 설치해야 합니다. 3단계에서 드라이버 프로젝트에 메시지 컴파일러 작업을 추가한 경우 계측 매니페스트가 컴파일되고 드라이버를 빌드할 때 리소스 파일이 생성됩니다. Windows 이벤트 명령줄 유틸리티(Wevtutil.exe)를 사용하여 매니페스트를 설치합니다. 매니페스트를 설치하는 구문은 다음과 같습니다.

wevtutil.exe imdrivermanifest

예를 들어 Evntdrv.sys 샘플 드라이버에 대한 매니페스트를 설치하려면 관리자 권한으로 명령 프롬프트 창을 열고(관리자 권한으로 실행) evntdrv.xml 파일이 있는 디렉터리로 이동하고 다음 명령을 입력합니다.

Wevtutil.exe im evntdrv.xml

추적 세션이 완료되면 다음 구문을 사용하여 매니페스트를 제거합니다.

wevtutil.exe umdrivermanifest

예를 들어 Eventdrv 샘플에 대한 매니페스트를 제거하려면 다음을 수행합니다.

Wevtutil.exe um evntdrv.xml

7. 드라이버 테스트하여 ETW 지원 확인

드라이버를 설치합니다. 드라이버를 실행하여 추적 작업을 생성합니다. 이벤트 뷰어 결과를 봅니다. Tracelog를 실행한 다음 이벤트 추적 로그를 처리하기 위한 도구인 Tracerpt를 실행하여 이벤트 추적 로그를 제어, 수집 및 볼 수도 있습니다.