다음을 통해 공유


EnableTraceEx2 함수(evntrace.h)

추적 세션 컨트롤러는 EnableTraceEx2 호출하여 ETW 이벤트 공급자가 추적 세션에 이벤트를 기록하는 방법을 구성합니다.

이 함수는 EnableTrace 대체하고 EnableTraceEx 함수를 .

통사론

ULONG WMIAPI EnableTraceEx2(
                 CONTROLTRACE_ID          TraceId,
  [in]           LPCGUID                  ProviderId,
  [in]           ULONG                    ControlCode,
  [in]           UCHAR                    Level,
  [in]           ULONGLONG                MatchAnyKeyword,
  [in]           ULONGLONG                MatchAllKeyword,
  [in]           ULONG                    Timeout,
  [in, optional] PENABLE_TRACE_PARAMETERS EnableParameters
);

매개 변수

TraceId

[in] ProviderId

구성하려는 이벤트 공급자의 공급자 ID(컨트롤 GUID)입니다.

[in] ControlCode

다음 컨트롤 코드 중 하나를 지정할 수 있습니다.

의미
EVENT_CONTROL_CODE_DISABLE_PROVIDER 세션이 공급자로부터 이벤트를 수신하지 않도록 세션 구성을 업데이트합니다.
EVENT_CONTROL_CODE_ENABLE_PROVIDER 세션이 공급자로부터 요청된 이벤트를 받도록 세션 구성을 업데이트합니다.
EVENT_CONTROL_CODE_CAPTURE_STATE 공급자가 해당 상태 정보를 기록할 것을 요청합니다.

[in] Level

공급자가 작성하려는 최대 이벤트 수준을 나타내는 값입니다. 공급자는 일반적으로 matchAnyKeyword 충족하고 MatchAllKeyword 조건을 이벤트 수준이 이 값보다 작거나 같은 경우 이벤트를 작성합니다.

Microsoft는 아래와 같이 수준 1-5의 의미 체계를 정의합니다. 값이 낮을수록 더 심각한 이벤트가 표시됩니다. 수준 각 값은 지정된 수준과 더욱 심각한 수준을 사용하도록 설정합니다. 예를 들어 TRACE_LEVEL_WARNING지정하면 소비자는 경고, 오류 및 중요한 이벤트를 받게 됩니다.

의미
TRACE_LEVEL_CRITICAL (1) 비정상적인 종료 또는 종료 이벤트
TRACE_LEVEL_ERROR (2) 심각한 오류 이벤트
TRACE_LEVEL_WARNING (3) 할당 오류와 같은 경고 이벤트
TRACE_LEVEL_INFORMATION (4) 오류 없는 정보 이벤트
TRACE_LEVEL_VERBOSE (5) 자세한 진단 이벤트

TRACE_LEVEL 상수는 evntrace.h정의됩니다. 동등한 WINMETA_LEVEL 상수는 winmeta.h정의됩니다.

[in] MatchAnyKeyword

공급자가 작성하려는 이벤트의 범주를 결정하는 키워드의 64비트 비트 마스크입니다. 일반적으로 공급자는 이벤트의 키워드 비트가 이 값에 설정된 비트의 일치하거나 이벤트에 키워드 비트가 설정되지 않은 경우 수준 충족하고 MatchAllKeyword 조건을 이벤트를 작성합니다.

[in] MatchAllKeyword

공급자가 작성하려는 이벤트를 제한하는 키워드의 64비트 비트 마스크입니다. 일반적으로 공급자는 이벤트의 키워드 비트가 이 값에 설정된 비트의 모든 일치하거나 이벤트에 키워드 비트가 설정되지 않은 경우 수준 충족하고 MatchAnyKeyword 조건을 이벤트를 작성합니다.

이 값은 자주 0으로 설정됩니다.

[in] Timeout

시간 제한 0이면 이 함수는 공급자 구성을 비동기적으로 시작하고 즉시 반환됩니다(즉, 공급자 콜백이 완료될 때까지 기다리지 않고 반환됨).

그렇지 않으면 이 함수는 공급자 구성을 시작하고 모든 공급자 콜백이 완료될 때까지 기다리는 것을 포함하여 구성이 완료될 때까지 대기하기 시작합니다. 지정된 시간 제한 전에 구성이 완료되면 이 함수는 ERROR_SUCCESS반환합니다. 그렇지 않으면 이 함수는 ERROR_TIMEOUT반환합니다.

영원히 기다리려면 INFINITE설정합니다.

[in, optional] EnableParameters

공급자를 사용하도록 설정하는 데 사용되는 추적 매개 변수입니다. 자세한 내용은 ENABLE_TRACE_PARAMETERS참조하세요.

반환 값

함수가 성공하면 반환 값이 ERROR_SUCCESS.

함수가 실패하면 반환 값은시스템 오류 코드 중 하나입니다. 다음은 몇 가지 일반적인 오류와 그 원인입니다.

  • ERROR_INVALID_PARAMETER

    매개 변수가 잘못되었습니다.

    이 문제는 다음 중 어느 것이라도 true인 경우에 발생할 수 있습니다.

    • ProviderId NULL.
    • TraceHandle0.
  • ERROR_TIMEOUT

    콜백 사용이 완료되기 전에 시간 제한 값이 만료되었습니다. 자세한 내용은 Timeout 매개 변수를 참조하세요.

  • ERROR_INVALID_FUNCTION

    공급자가 등록되지 않은 경우 수준을 업데이트할 수 없습니다.

  • ERROR_NO_SYSTEM_RESOURCES

    공급자를 사용하도록 설정할 수 있는 추적 세션 수를 초과했습니다.

  • ERROR_ACCESS_DENIED

    관리 권한이 있는 사용자, Performance Log Users 그룹의 사용자 및 LocalSystem, LocalService또는 NetworkService 실행 중인 서비스만 이벤트 공급자가 프로세스 간 세션에 사용하도록 설정할 수 있습니다. 제한된 사용자에게 이벤트 공급자를 사용하도록 설정할 수 있는 기능을 부여하려면 그룹에 추가하거나 eventAccessControl참조하세요.

    Windows XP 및 Windows 2000: 누구나 이벤트 공급자를 사용하도록 설정할 수 있습니다.

발언

이벤트 추적 컨트롤러는 이 함수를 호출하여 세션에 이벤트를 쓰는 이벤트 공급자를 구성합니다. 예를 들어 컨트롤러는 공급자로부터 이벤트 수집을 시작하거나, 공급자로부터 수집되는 이벤트의 수준 또는 키워드를 조정하거나, 공급자로부터 이벤트 수집을 중지하기 위해 이 함수를 호출할 수 있습니다.

공급자에 대한 사용 동작은 공급자가 사용하는 API에 따라 달라집니다.

  • RegisterTraceGuids 사용하는 공급자(예: TMF 기반 WPP 또는 MOF를 사용하는 공급자)는 레거시 사용 시스템("클래식 ETW"라고도 함)을 사용합니다. 레거시 공급자가 세션에 대해 사용하도록 설정되거나 다시 구성된 경우 ETW 런타임은 공급자에게 알리고 수준, MatchAnyKeyword 마스크의 하위 32비트 및 세션 ID에 대한 액세스를 제공합니다. 그런 다음 공급자는 자체 논리를 사용하여 사용하도록 설정해야 하는 이벤트를 결정하고 해당 이벤트를 지정된 세션으로 직접 보냅니다. 런타임에 ETW로 전송된 이벤트 데이터에는 이벤트의 디코딩 GUID 및 메시지 ID가 포함되지만 이벤트의 컨트롤 GUID, 수준 또는 키워드는 포함되지 않습니다. ETW는 공급자에게 필요한 권한이 있음을 확인한 다음 지정된 세션에 이벤트 데이터를 추가합니다.
    • 이벤트는 제어 GUID, 수준 또는 키워드 정보 없이 특정 세션으로 직접 전송되므로 ETW는 레거시 사용 시스템을 사용하는 공급자에 대해 추가 필터링 또는 라우팅을 수행할 수 없습니다. 각 이벤트는 둘 이상의 세션으로 라우팅될 수 있습니다.
  • EventRegister 사용하는 공급자(예: 매니페스트 기반 공급자 또는 TraceLogging 공급자)는 최신 사용 시스템("crimson ETW"라고도 함)을 사용합니다. 세션에 대해 최신 공급자를 사용하거나 다시 구성하면 ETW 런타임은 수준, 64비트 MatchAnyKeyword 마스크, 64비트 MatchAllKeyword 마스크 및 추적 컨트롤러에서 지정한 사용자 지정 공급자 쪽 필터링 데이터를 공급자에게 알릴 수 있습니다. 공급자는 자체 논리를 사용하여 사용하도록 설정할 이벤트를 결정하지만 대부분의 공급자는 EventProviderEnabled논리를 복제합니다. 공급자는 라우팅을 위해 활성화된 이벤트를 ETW로 보냅니다. ETW로 전송된 이벤트 데이터에는 이벤트의 컨트롤 GUID, 메시지 ID, 수준 및 키워드가 포함됩니다. 그런 다음 ETW는 적절하게 추가 필터링을 수행하여 이벤트를 적절한 세션으로 라우팅합니다.
    • 이벤트는 설명 정보를 사용하여 ETW로 전송되므로 ETW는 세션에 이벤트를 추가하기 전에 추가 필터링 및 라우팅을 수행할 수 있습니다. 적절한 경우 이벤트를 둘 이상의 세션으로 라우팅할 수 있습니다.

최신 사용 시스템(즉, EventRegister사용하는 공급자)을 사용하는 공급자의 경우 ETW는 EnableTraceEx2EnableParameters통해 추적 세션 컨트롤러에서 요청할 수 있는 여러 기능을 지원합니다. 자세한 내용은 EVENT_FILTER_DESCRIPTOR 참조하세요.

  • 스키마화된 필터링 - 공급자 쪽 필터링이라고도 하는 기존의 필터링 설정입니다. 컨트롤러는 FilterDataEnableCallback공급자에 전달되는 이진 개체로 사용자 지정 필터 집합을 정의합니다. 이러한 필터를 정의하고 해석하는 것은 컨트롤러 및 공급자의 맡입니다. 그런 다음 공급자는 EventWriteExFilter 매개 변수를 사용하여 공급자 쪽 필터링으로 인해 이벤트를 보내지 않아야 하는 세션을 나타낼 수 있습니다. 필터링할 수 있는 이진 개체의 형식과 형식이 정의되지 않았으므로 컨트롤러와 공급자를 긴밀하게 결합해야 합니다. TdhEnumerateProviderFilters 함수를 사용하여 매니페스트에 정의된 필터를 검색할 수 있습니다.
  • 범위 필터링 - 특정 공급자가 범위 필터에 지정된 조건을 충족하는지 여부에 따라 세션에 대해 활성화되거나 활성화되지 않습니다. PID(프로세스 ID), 실행 파일 이름, 앱 ID 및 앱 패키지 이름을 기반으로 필터링을 허용하는 여러 가지 유형의 범위 필터가 있습니다. 이 기능은 Windows 8.1, Windows Server 2012 R2 이상에서 지원됩니다.
  • Stackwalk 필터링 - 지정된 이벤트 ID 집합 또는 (TraceLogging 이벤트의 경우) 이벤트 이름에 대해서만 스택 워크를 수행하도록 ETW에 알깁니다. 이 기능은 Windows 8.1, Windows Server 2012 R2 이상에서 지원됩니다.
  • 특성 필터링 - 매니페스트 공급자의 경우 수준, 키워드, 이벤트 ID 또는 이벤트 이름과 같은 이벤트 특성을 기반으로 이벤트를 필터링할 수 있습니다.
  • 이벤트 페이로드 필터링 - 매니페스트 공급자의 경우 하나 이상의 조건자에 따라 논리 식을 충족하는지 여부에 따라 이벤트를 즉석에서 필터링할 수 있습니다.

메모

ETW는 강력한 페이로드 및 특성 필터링을 지원하지만, 이벤트는 주로 컨트롤 GUID, 수준 및 키워드를 통해 필터링된 범위 필터를 통해 필터링되어야 합니다. 공급자는 일반적으로 이벤트가 생성되거나 ETW로 전송되기 전에 공급자 코드에서 직접 제어 GUID, 수준 및 키워드 필터링을 수행합니다. 대부분의 공급자에서 수준 또는 키워드로 사용하지 않도록 설정된 이벤트는 시스템 성능에 거의 영향을 주지 않습니다. 마찬가지로 범위 필터에서 사용하지 않도록 설정된 공급자는 시스템 성능에 거의 영향을 주지 않습니다. 다른 종류의 필터링(수준 및 키워드 이외의 페이로드 또는 특성에 따라)은 일반적으로 공급자가 이벤트를 생성하고 ETW 런타임으로 보낸 후에 수행됩니다. 즉, ETW 필터링에서 이벤트를 어떤 세션에서도 기록해서는 안 된다고 판단하더라도 이벤트가 시스템 성능(이벤트를 준비하고 ETW로 보내는 데 소요된 CPU 시간)에 영향을 줍니다. 이러한 종류의 필터링은 추적 데이터 볼륨을 줄이는 데에만 효과적이며 추적 CPU 오버헤드를 줄이는 데는 효과적이지 않습니다.

EnableTraceEx2 때마다 해당 세션의 공급자에 대한 필터가 EnableTraceEx2 함수에 전달된 매개 변수로 정의된 새 매개 변수로 바뀝니다. 단일 EnableTraceEx2 호출에 전달된 여러 필터를 추가 효과와 결합할 수 있지만 후속 호출에서 전달된 필터는 이전 필터 집합을 대체합니다.

필터링을 사용하지 않도록 설정하고 로깅 세션에서 모든 공급자/이벤트를 사용하도록 설정하려면 FilterDescCount 멤버가 0으로 설정된 ENABLE_TRACE_PARAMETERS 구조를 가리키는 EnableParameters 매개 변수를 사용하여 EnableTraceEx2 호출합니다.

EnableTraceEx2 함수에 전달된 각 필터는 EVENT_FILTER_DESCRIPTORType 멤버에 의해 지정됩니다. EVENT_FILTER_DESCRIPTOR 구조체의 배열은 EnableParameters 매개 변수에 전달된 ENABLE_TRACE_PARAMETERS 구조체에서 EnableTraceEx2 함수에 전달됩니다.

각 필터 유형(특정 형식 멤버)은 EnableTraceEx2 함수에 대한 호출에서 한 번만 나타날 수 있습니다. 일부 필터 형식을 사용하면 여러 조건을 단일 필터에 포함할 수 있습니다. EnableTraceEx2 호출에 포함할 수 있는 최대 필터 수는 MAX_EVENT_FILTERS_COUNT 설정됩니다(Evntprov.h 헤더 파일에 정의되며, 이후 버전의 Windows SDK에서는 값이 변경될 수 있음).

각 필터 형식에는 EVENT_FILTER_DESCRIPTOR 구조의 특정 Type 멤버에 따라 고유한 크기 또는 엔터티 제한이 있습니다. 아래 목록은 이러한 제한을 나타냅니다.

  • EVENT_FILTER_TYPE_SCHEMATIZED

    • 필터 크기 제한: MAX_EVENT_FILTER_DATA_SIZE(1024)
    • 허용되는 요소 수: 공급자 및 컨트롤러에서 정의
  • EVENT_FILTER_TYPE_PID

    • 필터 크기 제한: MAX_EVENT_FILTER_DATA_SIZE(1024)
    • 허용되는 요소 수: MAX_EVENT_FILTER_PID_COUNT(8)
  • EVENT_FILTER_TYPE_EXECUTABLE_NAME

    • 필터 크기 제한: MAX_EVENT_FILTER_DATA_SIZE(1024)
    • 허용되는 요소 수: 세미콜론으로 구분된 여러 실행 파일 이름을 포함할 수 있는 단일 문자열입니다.
  • EVENT_FILTER_TYPE_PACKAGE_ID

    • 필터 크기 제한: MAX_EVENT_FILTER_DATA_SIZE(1024)
    • 허용되는 요소 수: 세미콜론으로 구분된 여러 패키지 ID를 포함할 수 있는 단일 문자열입니다.
  • EVENT_FILTER_TYPE_PACKAGE_APP_ID

    • 필터 크기 제한: MAX_EVENT_FILTER_DATA_SIZE(1024)
    • 허용되는 요소 수: 세미콜론으로 구분된 여러 패키지 상대 앱 ID(PRAID)를 포함할 수 있는 단일 문자열입니다.
  • EVENT_FILTER_TYPE_PAYLOAD

    • 필터 크기 제한: MAX_EVENT_FILTER_PAYLOAD_SIZE(4096)
    • 허용되는 요소 수: 1
  • EVENT_FILTER_TYPE_EVENT_ID

    • 필터 크기 제한: 정의되지 않음
    • 허용되는 요소 수: MAX_EVENT_FILTER_EVENT_ID_COUNT(64)
  • EVENT_FILTER_TYPE_STACKWALK

    • 필터 크기 제한: 정의되지 않음
    • 허용되는 요소 수: MAX_EVENT_FILTER_EVENT_ID_COUNT(64)

키워드는 이벤트 범주를 정의합니다. 예를 들어 공급자가 InitializationKeyword = (키워드 비트 0), FileOperationKeyword = (키워드 비트 1) 및 CalculationKeyword = (키워드 비트 2)를 정의하는 경우 matchAnyKeyword 설정할 수 있습니다(InitializationKeyword | CalculationKeyword) = 초기화 및 계산 이벤트를 수신하지만 파일 이벤트는 수신하지 않는 5입니다.

최신(매니페스트 기반 또는 TraceLogging) 공급자와 함께 사용할 경우 0MatchAnyKeyword 값은 0xFFFFFFFFFFFFFFFFMatchAnyKeyword 값과 동일하게 처리됩니다. 즉, 모든 이벤트 키워드를 사용하도록 설정합니다. 그러나 이 동작은 레거시(MOF 또는 TMF 기반 WPP) 공급자에는 적용되지 않습니다. 레거시 공급자의 모든 이벤트 키워드를 사용하도록 설정하려면 MatchAnyKeyword0xFFFFFFFF설정합니다. 레거시 및 최신 공급자의 모든 이벤트 키워드를 사용하도록 설정하려면 MatchAnyKeyword0xFFFFFFFFFFFFFFFF설정합니다.

이벤트의 키워드가 0이면 공급자는 MatchAnyKeyword 및 matchAllKeyword 마스크를 관계없이 세션에 이벤트를 씁니다. (이 동작은 EVENT_ENABLE_PROPERTY_IGNORE_KEYWORD_0 플래그를 사용하여 사용하지 않도록 설정할 수 있습니다.)

공급자 그룹을 사용하도록 설정하려는 경우 EnableParametersEnableProperty 멤버에서 EVENT_ENABLE_PROPERTY_PROVIDER_GROUP 플래그를 사용합니다.

EnableTraceEx2호출하면 공급자가 아직 등록되어 있거나 등록되지 않을 수 있습니다. 공급자가 이미 등록된 경우 ETW는 공급자의 콜백 함수(있는 경우)를 호출하고 세션이 이벤트 수신을 시작합니다. 공급자가 아직 등록되지 않은 경우 ETW는 공급자가 등록한 직후 공급자의 콜백 함수(있는 경우)를 호출하고 세션은 이벤트 수신을 시작합니다. 공급자가 아직 등록되지 않은 경우 공급자의 콜백 함수는 원본 ID를 받지 못합니다.

공급자가 등록되어 있고 세션에 이미 사용하도록 설정된 경우 EnableTraceEx2 다시 호출하여 Level, matchAnyKeyword, MatchAllKeyword 매개 변수 및 EnablePropertyEnableFilterDesc EnableParameters멤버를 업데이트할 수 있습니다.

Windows 8.1, Windows Server 2012 R2 이상에서는 EnableTraceEx2 함수와 ENABLE_TRACE_PARAMETERSEVENT_FILTER_DESCRIPTOR 구조체에서 이벤트 페이로드, 범위 및 스택 워크 필터를 사용하여 로거 세션의 특정 조건을 필터링할 수 있습니다. 이벤트 페이로드 필터에 대한 자세한 내용은 TdhCreatePayloadFilterTdhAggregatePayloadFilters 함수 및 ENABLE_TRACE_PARAMETERS, EVENT_FILTER_DESCRIPTORPAYLOAD_FILTER_PREDICATE 구조를 참조하세요.

EnableTraceEx2특수 시스템 추적 공급자 이벤트를 사용하거나 사용하지 않도록 설정할 수 없습니다. StartTrace추적을 처음 시작할 때 EVENT_TRACE_PROPERTIESEnableFlags 필드를 통해서만 사용하도록 설정할 수 있습니다.

Windows 11부터 시스템 추적 공급자 이벤트는 EnableTraceEx2사용하여 사용하도록 설정할 수 있습니다.

최대 8개의 추적 세션은 동일한 최신(매니페스트 기반 또는 TraceLogging) 공급자에서 이벤트를 사용하도록 설정하고 받을 수 있습니다. 그러나 하나의 추적 세션만 레거시(MOF, TMF 기반 WPP) 공급자를 사용하도록 설정할 수 있습니다. 둘 이상의 세션이 레거시 공급자를 사용하도록 설정하려고 하면 두 번째 세션에서 동일한 공급자를 사용하도록 설정하면 첫 번째 세션이 이벤트 수신을 중지합니다. 예를 들어 세션 A가 레거시 공급자를 사용하도록 설정한 다음 세션 B가 동일한 공급자를 사용하도록 설정한 경우 세션 B만 해당 공급자로부터 이벤트를 받습니다.

세션이 공급자를 사용하지 않도록 설정할 때까지 공급자가 세션에 대해 활성화된 상태로 유지됩니다. 세션을 시작한 애플리케이션이 공급자를 사용하지 않도록 설정하지 않고 종료되는 경우 공급자는 계속 사용하도록 설정됩니다.

매니페스트 기반 공급자를 사용하도록 설정하는 데 사용되는 수준 및 키워드를 확인하려면 다음 명령 중 하나를 사용합니다.

  • 공급자 이름 logman 쿼리 공급자
  • wevtutil gp provider-name

클래식 공급자의 경우 공급자가 잠재적인 컨트롤러에 심각도 수준을 문서화하고 사용할 수 있도록 하거나 지원하는 플래그를 사용하도록 설정해야 합니다. 공급자가 컨트롤러에서 사용하도록 설정하려는 경우 공급자는 심각도 수준에 대해 0을 수락하고 플래그를 사용하도록 설정하고 0을 기본 로깅을 수행하도록 요청으로 해석해야 합니다(무엇이든).

EnableTraceEx2 사용하여 클래식 공급자를 사용하도록 설정하는 경우 다음 변환이 수행됩니다.

  • Level 매개 변수는 EnableTraceEnableLevel 매개 변수를 설정하는 것과 같습니다.
  • MatchAnyKeyword 키워드 값이 64비트 값에서 32비트 값으로 잘린다는 점을 제외하고 EnableTraceEnableFlag 매개 변수를 설정하는 것과 같습니다.
  • ControlCallback 콜백에서 공급자는 GetTraceEnableLevel 호출하여 수준을 얻고 GetTraceEnableFlags 사용 플래그를 가져올 수 있습니다.
  • 다른 매개 변수는 사용되지 않습니다.

예제

다음 예제에서는 TdhCreatePayloadFilter 사용하여 페이로드 필터와 EnableTraceEx2 사용하고 TdhAggregatePayloadFilters 함수를 로거 세션의 특정 조건을 필터링하는 방법을 보여 줍니다.

#define INITGUID
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <strsafe.h>
#include <evntrace.h>
#include <tdh.h>

#define MAXIMUM_SESSION_NAME 1024

#define PATH_TO_MANIFEST_FILE L"c:\\ExampleManifest.man"

//
// The following definitions would be found in the include file generated by
// message compiler from the manifest file.
//

// Provider Example-Provider Event Count 2
EXTERN_C __declspec(selectany) const GUID EXAMPLE_PROVIDER = {0x37a59b93, 0xbb25, 0x4cee, {0x97, 0xaa, 0x8b, 0x6a, 0xcd, 0xc, 0x4d, 0xf8}};

//
// Event Descriptors
//
EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR Example_Event_1 = { 0x1, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0 };
#define Example_Event_1_value 0x1
EXTERN_C __declspec(selectany) const EVENT_DESCRIPTOR Example_Event_2 = { 0x2, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0 };
#define Example_Event_2_value 0x2

//
// (End of snippet from include file)
//

// Allocate an EVENT_TRACE_PROPERTIES structure and set the needed logging session properties
PEVENT_TRACE_PROPERTIES AllocateTraceProperties(
    _In_opt_ PCWSTR LoggerName,
    _In_opt_ PCWSTR LogFileName
)
{
    PEVENT_TRACE_PROPERTIES TraceProperties = NULL;
    ULONG BufferSize;

    BufferSize = sizeof(EVENT_TRACE_PROPERTIES) +
        (MAXIMUM_SESSION_NAME + MAX_PATH) * sizeof(WCHAR);

    TraceProperties = (PEVENT_TRACE_PROPERTIES)malloc(BufferSize);
    if (TraceProperties == NULL) {
        printf("Unable to allocate %d bytes for properties structure.\n", BufferSize);
        goto Exit;
    }

    //
    // Set the session properties.
    //
    ZeroMemory(TraceProperties, BufferSize);
    TraceProperties->Wnode.BufferSize = BufferSize;
    TraceProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
    TraceProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
    TraceProperties->LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES) +
        (MAXIMUM_SESSION_NAME * sizeof(WCHAR));

    if (LoggerName != NULL) {
        StringCchCopyW((LPWSTR)((PCHAR)TraceProperties + TraceProperties->LoggerNameOffset),
            MAXIMUM_SESSION_NAME,
            LoggerName);
    }

    if (LogFileName != NULL) {
        StringCchCopyW((LPWSTR)((PCHAR)TraceProperties + TraceProperties->LogFileNameOffset),
            MAX_PATH,
            LogFileName);
    }

Exit:
    return TraceProperties;
}

// Free the EVENT_TRACE_PROPERTIES structure previously allocated
VOID FreeTraceProperties(
    _In_ PEVENT_TRACE_PROPERTIES TraceProperties
)
{
    free(TraceProperties);
    return;
}

// Set the values needed in a PAYLOAD_FILTER_PREDICATE for a single payload filter
FORCEINLINE VOID PayloadPredicateCreate(
    _Out_ PAYLOAD_FILTER_PREDICATE* Predicate,
    _In_ PCWSTR FieldName,
    USHORT CompareOp,
    PCWSTR Value
)
{
    Predicate->FieldName = (PWSTR)FieldName;
    Predicate->CompareOp = CompareOp;
    Predicate->Value = (PWSTR)Value;
    return;
}

int __cdecl wmain()
{
    UINT i;
    PVOID EventFilters[2];
    EVENT_FILTER_DESCRIPTOR FilterDescriptor;
    UINT PredicateCount;
    PAYLOAD_FILTER_PREDICATE Predicates[3];
    ULONG FilterCount;
    ULONG Status = ERROR_SUCCESS;
    TRACEHANDLE SessionHandle = 0;
    PEVENT_TRACE_PROPERTIES TraceProperties;
    BOOLEAN TraceStarted = FALSE;
    PCWSTR LoggerName = L"MyTrace";
    ENABLE_TRACE_PARAMETERS EnableParameters;

    ZeroMemory(EventFilters, sizeof(EventFilters));
    ZeroMemory(Predicates, sizeof(Predicates));
    TraceProperties = NULL;
    FilterCount = 0;

    //
    // Load the manifest for the provider
    //
    Status = TdhLoadManifest((PWSTR)PATH_TO_MANIFEST_FILE);
    if (Status != ERROR_SUCCESS) {
        printf("TdhCreatePayloadFilter() failed with %lu\n", Status);
        goto Exit;
    }

    //
    // Create predicates that match the following high-level expression:
    //
    // INCLUDE Example_Event_1 IF
    //     Example_Event_1.Initiator == "User" AND
    //     7 <= Example_Event_1.Level <= 16
    //
    PredicateCount = 0;

    PayloadPredicateCreate(
        &Predicates[PredicateCount++],
        (PWSTR)L"Initiator",
        PAYLOADFIELD_IS,
        (PWSTR)L"User");

    PayloadPredicateCreate(
        &Predicates[PredicateCount++],
        L"Level",
        PAYLOADFIELD_BETWEEN,
        L"7,16");

    Status = TdhCreatePayloadFilter(
        &EXAMPLE_PROVIDER,
        &Example_Event_1,
        FALSE,      // Match all predicates (AND)
        PredicateCount,
        Predicates,
        &EventFilters[FilterCount++]);
    if (Status != ERROR_SUCCESS) {
        printf("TdhCreatePayloadFilter() failed with %lu\n", Status);
        goto Exit;
    }

    //
    // Create predicates that match the following high-level expression:
    // INCLUDE Example_Event_2 IF
    //      Example_Event_2.Title CONTAINS "UNI" OR
    //      Example_Event_2.InstanceId == {0E95CFBC-58D4-44BA-BE40-E63A853536DF} OR
    //      Example_Event_2.ErrorCode != 0      //
    PredicateCount = 0;

    PayloadPredicateCreate(
        &Predicates[PredicateCount++],
        L"Title",
        PAYLOADFIELD_CONTAINS,
        L"UNI");

    PayloadPredicateCreate(
        &Predicates[PredicateCount++],
        L"InstanceId",
        PAYLOADFIELD_IS,
        L" {0E95CFBC-58D4-44BA-BE40-E63A853536DF}");

    PayloadPredicateCreate(
        &Predicates[PredicateCount++],
        L"ErrorCode",
        PAYLOADFIELD_NE,
        L"0");

    Status = TdhCreatePayloadFilter(
        &EXAMPLE_PROVIDER,
        &Example_Event_2,
        FALSE,      // Match any predicates (OR)
        PredicateCount,
        Predicates,
        &EventFilters[FilterCount++]);
    if (Status != ERROR_SUCCESS) {
        printf("TdhCreatePayloadFilter() failed with %lu\n", Status);
        goto Exit;
    }

    //
    // Combine the interim filters into a final filter descriptor.
    //
    Status = TdhAggregatePayloadFilters(
        FilterCount,
        EventFilters,
        NULL,
        &FilterDescriptor);
    if (Status != ERROR_SUCCESS) {
        printf("TdhAggregatePayloadFilters() failed with %lu\n", Status);
        goto Exit;
    }

    //
    // Clean up the interim filters
    //
    for (i = 0; i < FilterCount; i++) {

        Status = TdhDeletePayloadFilter(&EventFilters[i]);
        if (Status != ERROR_SUCCESS) {
            printf("TdhDeletePayloadFilter() failed with %lu\n", Status);
            goto Exit;
        }
    }

    //
    // Create a new trace session
    //
    //
    // Allocate EVENT_TRACE_PROPERTIES structure and perform some
    // basic initialization.
    //
    // N.B. LoggerName will be populated during StartTrace call.
    //
    TraceProperties = AllocateTraceProperties(NULL, L"SystemTrace.etl");
    if (TraceProperties == NULL) {
        Status = ERROR_OUTOFMEMORY;
        goto Exit;
    }

    TraceProperties->LogFileMode = EVENT_TRACE_FILE_MODE_SEQUENTIAL | EVENT_TRACE_SYSTEM_LOGGER_MODE;
    TraceProperties->MaximumFileSize = 100; // Limit file size to 100MB max
    TraceProperties->BufferSize = 512; // Use 512KB trace buffers
    TraceProperties->MinimumBuffers = 8;
    TraceProperties->MaximumBuffers = 64;

    Status = StartTraceW(&SessionHandle, LoggerName, TraceProperties);
    if (Status != ERROR_SUCCESS) {
        printf("StartTrace() failed with %lu\n", Status);
        goto Exit;
    }

    TraceStarted = TRUE;

    //
    // Enable the provider to a trace session with filtering enabled on the
    // provider
    //
    ZeroMemory(&EnableParameters, sizeof(EnableParameters));
    EnableParameters.Version = ENABLE_TRACE_PARAMETERS_VERSION_2;
    EnableParameters.EnableFilterDesc = &FilterDescriptor;
    EnableParameters.FilterDescCount = 1;

    Status = EnableTraceEx2(
        SessionHandle,
        &EXAMPLE_PROVIDER,
        EVENT_CONTROL_CODE_ENABLE_PROVIDER,
        TRACE_LEVEL_VERBOSE,
        0,
        0,
        0,
        &EnableParameters);
    if (Status != ERROR_SUCCESS) {
        printf("EnableTraceEx2() failed with %lu\n", Status);
        goto Exit;
    }

    //
    // Clean up the payload descriptor
    //
    Status = TdhCleanupPayloadEventFilterDescriptor(&FilterDescriptor);
    if (Status != ERROR_SUCCESS) {
        printf("TdhCleanupPayloadEventFilterDescriptor() failed with %lu\n", Status);
        goto Exit;
    }

    //
    // Collect trace for 30 seconds
    //
    Sleep(30 * 1000);

Exit:

    //
    // Stop tracing.
    //
    if (TraceStarted != FALSE) {
        Status = ControlTraceW(SessionHandle, NULL, TraceProperties, EVENT_TRACE_CONTROL_STOP);
        if (Status != ERROR_SUCCESS) {
            printf("StopTrace() failed with %lu\n", Status);
        }
    }

    if (TraceProperties != NULL) {
        FreeTraceProperties(TraceProperties);
    }

    TdhUnloadManifest((PWSTR)PATH_TO_MANIFEST_FILE);

    return Status;
}

요구 사항

요구
지원되는 최소 클라이언트 Windows 7 [데스크톱 앱 | UWP 앱]
지원되는 최소 서버 Windows Server 2008 R2 [데스크톱 앱 | UWP 앱]
대상 플랫폼 Windows
헤더 evntrace.h
라이브러리 Windows 8.1 및 Windows Server 2012 R2의 Sechost.lib; Windows 8, Windows Server 2012, Windows 7 및 Windows Server 2008 R2의 Advapi32.lib
DLL Windows 8.1 및 Windows Server 2012 R2에서 Sechost.dll; Windows 8, Windows Server 2012, Windows 7 및 Windows Server 2008 R2의 Advapi32.dll

참고 항목

StartTrace

ControlTrace

EnableCallback

ENABLE_TRACE_PARAMETERS

EVENT_FILTER_DESCRIPTOR