EnableTraceEx2 関数 (evntrace.h)

トレース セッション コントローラーは EnableTraceEx2 を 呼び出して、ETW イベント プロバイダーがイベントをトレース セッションに記録する方法を構成します。

この関数は、EnableTrace 関数と EnableTraceEx 関数よりも優先されます。

構文

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

パラメーター

[in] TraceHandle

プロバイダーを構成するイベント トレース セッションのハンドル。 StartTrace 関数は、新しいトレースが開始されたときにこのハンドルを返します。 既存のトレースのハンドルを取得するには、ControlTrace を使用してトレースの名前に基づいてトレース プロパティを照会し、返されたEVENT_TRACE_PROPERTIESデータの Wnode.HistoricalContext フィールドからハンドルを取得します。

[in] ProviderId

構成するイベント プロバイダーのプロバイダー ID (制御 GUID)。

[in] ControlCode

次のいずれかの制御コードを指定できます。

意味
EVENT_CONTROL_CODE_DISABLE_PROVIDER セッションがプロバイダーからイベントを受信しないように、セッション構成を更新します。
EVENT_CONTROL_CODE_ENABLE_PROVIDER セッション構成を更新して、セッションがプロバイダーから要求されたイベントを受信するようにします。
EVENT_CONTROL_CODE_CAPTURE_STATE プロバイダーが状態情報をログに記録することを要求します。

[in] Level

プロバイダーが書き込むイベントの最大レベルを示す 値。 プロバイダーは、通常、イベントのレベルがこの値以下の場合、 MatchAnyKeywordMatchAllKeyword の条件を満たすだけでなく、イベントを書き込みます。

Microsoft では、次に示すように、レベル 1 から 5 のセマンティクスを定義します。 値が小さいほど、より重大なイベントを示します。 Level の各値は、指定されたレベルとより厳しいレベルをすべて有効にします。 たとえば、 を指定 TRACE_LEVEL_WARNINGすると、コンシューマーは警告、エラー、重大なイベントを受け取ります。

意味
TRACE_LEVEL_CRITICAL (1) 異常終了イベントまたは終了イベント
TRACE_LEVEL_ERROR (2) 重大なエラー イベント
TRACE_LEVEL_WARNING (3) 割り当てエラーなどの警告イベント
TRACE_LEVEL_INFORMATION (4) エラー以外の情報イベント
TRACE_LEVEL_VERBOSE (5) 詳細な診断イベント

定数は TRACE_LEVELevntrace.h で定義されます。 同等 WINMETA_LEVEL の定数は winmeta.h で定義されます。

[in] MatchAnyKeyword

プロバイダーが書き込むイベントのカテゴリを決定するキーワードの 64 ビット ビットマスク。 通常、プロバイダーは、イベントのキーワード (keyword) ビットがこの値に設定されているビットのいずれかと一致する場合、または Level とMatchAllKeyword の条件を満たすだけでなく、イベントにキーワード (keyword)ビットが設定されていない場合にイベントを書き込みます。

[in] MatchAllKeyword

プロバイダーが書き込むイベントを制限するキーワードの 64 ビット ビットマスク。 プロバイダーは通常、イベントのキーワード (keyword) ビットがこの値に設定されているすべてのビットと一致する場合、または Level およびMatchAnyKeyword 条件を満たすだけでなく、イベントにキーワード (keyword)ビットが設定されていない場合にイベントを書き込みます。

この値は、多くの場合、0 に設定されます。

[in] Timeout

Timeout が 0 の場合、この関数はプロバイダーの構成を非同期的に開始し、すぐに返されます (つまり、プロバイダーのコールバックが完了するのを待たずにが返されます)。

それ以外の場合、この関数はプロバイダーの構成を開始し、すべてのプロバイダー コールバックの完了を待機するなど、構成の完了の待機を開始します。 指定したタイムアウトの前に構成が完了すると、この関数は ERROR_SUCCESSを返します。 それ以外の場合、この関数は ERROR_TIMEOUTを返します。

永遠に待つには、 INFINITE に設定します。

[in, optional] EnableParameters

プロバイダーを有効にするために使用されるトレース パラメーター。 詳細については、「 ENABLE_TRACE_PARAMETERS」を参照してください。

戻り値

関数が成功した場合、戻り値は ERROR_SUCCESS

関数が失敗した場合、戻り値は システム エラー コードの 1 つです。 一般的なエラーとその原因を次に示します。

  • ERROR_INVALID_PARAMETER

    パラメーターが正しくありません。

    これは、次のいずれかに該当する場合に発生する可能性があります。

    • ProviderIdNULL です
    • TraceHandle0 です
  • ERROR_TIMEOUT

    タイムアウト値は、有効化コールバックが完了する前に期限切れになりました。 詳細については、 Timeout パラメーターを参照してください。

  • ERROR_INVALID_FUNCTION

    プロバイダーが登録されていない場合は、レベルを更新できません。

  • ERROR_NO_SYSTEM_RESOURCES

    プロバイダーを有効にできるトレース セッションの数を超えました。

  • ERROR_ACCESS_DENIED

    管理者特権を持つユーザー、グループ内のPerformance Log Usersユーザー、および 、、または NetworkService としてLocalServiceLocalSystem実行されているサービスを持つユーザーのみが、クロスプロセス セッションに対してイベント プロバイダーを有効にすることができます。 制限付きユーザーにイベント プロバイダーを有効にする機能を付与するには、グループに Performance Log Users 追加するか、「 EventAccessControl」を参照してください。

    Windows XP と Windows 2000: イベント プロバイダーは誰でも有効にできます。

解説

イベント トレース コントローラーは、この関数を呼び出して、セッションにイベントを書き込むイベント プロバイダーを構成します。 たとえば、コントローラーは、プロバイダーからのイベントの収集を開始したり、プロバイダーから収集されるイベントのレベルまたはキーワードを調整したり、プロバイダーからのイベントの収集を停止したりするために、この関数を呼び出す場合があります。

プロバイダーの有効化動作は、プロバイダーが使用する API によって異なります。

  • RegisterTraceGuids を使用するプロバイダー (TMF ベースの WPP または MOF を使用するプロバイダーなど) は、レガシ有効化システム ("クラシック ETW" と呼ばれることもあります) を使用します。 セッションに対してレガシ プロバイダーが有効または再構成されると、ETW ランタイムはプロバイダーに通知し、レベル、MatchAnyKeyword マスクの下位 32 ビット、およびセッション ID へのアクセスを提供します。 その後、プロバイダーは独自のロジックを使用して、有効にする必要があるイベントを決定し、それらのイベントを指定されたセッションに直接送信します。 実行時に ETW に送信されるイベント データには、イベントのデコード GUID とメッセージ ID が含まれますが、イベントのコントロール GUID、レベル、キーワードは含まれません。 ETW は、プロバイダーが必要なアクセス許可を持っていることを確認し、指定したセッションにイベント データを追加します。
    • イベントは、制御 GUID、レベル、またはキーワード (keyword)情報を持たない特定のセッションに直接送信されるため、ETW はレガシ有効化システムを使用するプロバイダーに対して追加のフィルター処理やルーティングを実行できません。 各イベントは、複数のセッションにルーティングできません。
  • EventRegister を使用するプロバイダー (マニフェスト ベースのプロバイダーやトレース ログ プロバイダーなど) では、最新の有効化システム ("真紅 ETW" と呼ばれることもあります) が使用されます。 セッションに対して最新のプロバイダーが有効または再構成されると、ETW ランタイムは、レベル、64 ビットの MatchAnyKeyword マスク、64 ビットの MatchAllKeyword マスク、およびトレース コントローラーで指定されたカスタム プロバイダー側のフィルター 処理データをプロバイダーに通知します。 その後、プロバイダーは独自のロジックを使用して有効にする必要があるイベントを決定しますが、ほとんどのプロバイダーは EventProviderEnabled のロジックを複製するだけです。 プロバイダーは、ルーティングのために有効なイベントを ETW に送信します。 ETW に送信されるイベント データには、イベントのコントロール GUID、メッセージ ID、レベル、キーワードが含まれます。 その後、ETW は必要に応じて追加のフィルター処理を実行し、イベントを適切なセッションにルーティングします。
    • イベントは説明情報を使用して ETW に送信されるため、ETW はイベントをセッションに追加する前に追加のフィルター処理とルーティングを実行できます。 必要に応じて、イベントを複数のセッションにルーティングできます。

最新の有効化システムを使用するプロバイダー (つまり 、EventRegister を使用するプロバイダー) の場合、ETW では 、EnableTraceEx2EnableParameters を介してトレース セッション コントローラーによって要求できるいくつかの機能がサポートされています。 (詳細については 、「EVENT_FILTER_DESCRIPTOR 」を参照してください。

  • スキーマ化されたフィルター処理 - これは従来のフィルター設定であり、プロバイダー側のフィルター処理とも呼ばれます。 コントローラーは、フィルターのカスタム セットを、 EnableCallbackFilterData でプロバイダーに渡されるバイナリ オブジェクトとして定義します。 これらのフィルターを定義して解釈するには、コントローラーとプロバイダーが必要です。 プロバイダーは、EventWriteEx Filter パラメーターを使用して、プロバイダー側のフィルター処理のためにイベントを送信しないセッションを示すことができます。 フィルター処理できるバイナリ オブジェクトの型と形式が定義されていないため、コントローラーとプロバイダーの密接な結合が必要です。 TdhEnumerateProviderFilters 関数を使用して、マニフェストで定義されているフィルターを取得できます。
  • スコープ のフィルター処理 - 特定のプロバイダーは、スコープ フィルターで指定された条件を満たしているかどうかに基づいて、セッションに対して有効になっているか、有効になっていません。 プロセス ID (PID)、実行可能ファイル名、アプリ ID、アプリ パッケージ名に基づくフィルター処理を可能にするスコープ フィルターには、いくつかの種類があります。 この機能は、Windows 8.1、Windows Server 2012 R2 以降でサポートされています。
  • Stackwalk フィルタリング - 特定のイベント ID セットまたは (TraceLogging イベントの場合) イベント名に対してのみスタック ウォークを実行するように ETW に通知します。 この機能は、Windows 8.1、Windows Server 2012 R2 以降でサポートされています。
  • 属性のフィルター処理 - マニフェスト プロバイダーの場合、イベントは、レベル、キーワード (keyword)、イベント ID、イベント名などのイベント属性に基づいてフィルター処理できます。
  • イベント ペイロードのフィルター処理 - マニフェスト プロバイダーの場合、イベントは、1 つ以上の述語に基づいて論理式を満たすかどうかに基づいて、その場でフィルター処理できます。

注意

ETW では強力なペイロードと属性のフィルター処理がサポートされていますが、イベントは主にフィルター処理ベースのスコープ フィルター、またはコントロール GUID、レベル、およびキーワード (keyword)を使用してフィルター処理する必要があります。 通常、プロバイダーは、イベントが生成または ETW に送信される前に、プロバイダーのコードで直接、コントロール GUID、レベル、およびキーワード (keyword)フィルター処理を実行します。 ほとんどのプロバイダーでは、レベルまたはキーワード (keyword)によって無効になっているイベントは、システムのパフォーマンスにほとんど影響しません。 同様に、スコープ フィルターによって無効になっているプロバイダーは、システムのパフォーマンスにほとんど影響しません。 他の種類のフィルター処理 (レベルとキーワード (keyword)以外のペイロードまたは属性に基づく) は、通常、プロバイダーがイベントを生成して ETW ランタイムに送信した後に実行されます。つまり、イベントはシステム パフォーマンス (イベントの準備と ETW への送信に費やされた CPU 時間) に影響します。ETW フィルター処理でイベントを記録する必要があると判断された場合でも、そのイベントはセッションによって記録されません。 この種のフィルター処理は、トレース データ ボリュームを減らす場合にのみ有効であり、トレース CPU オーバーヘッドを削減する場合ほど有効ではありません。

EnableTraceEx2 が呼び出されるたびに、そのセッションのプロバイダーのフィルターは、EnableTraceEx2 関数に渡されるパラメーターによって定義された新しいパラメーターに置き換えられます。 1 つの EnableTraceEx2 呼び出しで渡された複数のフィルターを追加効果と組み合わせることができますが、後続の呼び出しで渡されたフィルターは、以前のフィルターのセットに置き換えられます。

フィルター処理を無効にし、ログ セッション内のすべてのプロバイダー/イベントを有効にするには、FilterDescCount メンバーが 0 に設定されたENABLE_TRACE_PARAMETERS構造体を指す EnableParameters パラメーターを指定して EnableTraceEx2 を呼び出します。

EnableTraceEx2 関数に渡される各フィルターは、EVENT_FILTER_DESCRIPTORType メンバーによって指定されます。 enableParameters パラメーターで EnableTraceEx2 関数に渡されるENABLE_TRACE_PARAMETERS構造体には、EVENT_FILTER_DESCRIPTOR構造体の配列が渡されます。

フィルターの各種類 (特定の Type メンバー) は 、EnableTraceEx2 関数の呼び出しで 1 回だけ表示できます。 フィルターの種類によっては、1 つのフィルターに複数の条件を含めることができます。 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)
    • 使用できる要素の数: 複数の実行可能ファイル名をセミコロンで区切って含めることができる 1 つの文字列。
  • EVENT_FILTER_TYPE_PACKAGE_ID

    • フィルター サイズの制限: MAX_EVENT_FILTER_DATA_SIZE (1024)
    • 使用できる要素の数: セミコロンで区切られた複数のパッケージ ID を含めることができる 1 つの文字列。
  • EVENT_FILTER_TYPE_PACKAGE_APP_ID

    • フィルター サイズの制限: MAX_EVENT_FILTER_DATA_SIZE (1024)
    • 使用できる要素の数: 複数のパッケージ相対アプリ ID (PRAID) をセミコロンで区切って含めることができる 1 つの文字列。
  • 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 = 0x1 (キーワード (keyword) ビット 0)、FileOperationKeyword = 0x2 (キーワード (keyword) ビット 1)、CalculationKeyword = 0x4 (キーワード (keyword) ビット 2) を定義している場合は、MatchAnyKeyword を (InitializationKeyword |CalculationKeyword) = 初期化イベントと計算イベントを受け取るが、ファイル イベントを受信しない場合は 5。

モダン (マニフェスト ベースまたは TraceLogging) プロバイダーで使用すると、 の 0MatchAnyKeyword 値は、MatchAnyKeyword0xFFFFFFFFFFFFFFFFと同じように扱われます。つまり、すべてのイベント キーワードが有効になります。 ただし、この動作はレガシ (MOF または TMF ベースの WPP) プロバイダーには適用されません。 レガシ プロバイダーからのすべてのイベント キーワードを有効にするには、 MatchAnyKeyword を に 0xFFFFFFFF設定します。 レガシ プロバイダーとモダン プロバイダーの両方からすべてのイベント キーワードを有効にするには、 MatchAnyKeyword を に設定します 0xFFFFFFFFFFFFFFFF

イベントのキーワード (keyword)が 0 の場合、MatchAnyKeyword マスクと MatchAllKeyword マスクに関係なく、プロバイダーはイベントをセッションに書き込みます。 (この動作は、 EVENT_ENABLE_PROPERTY_IGNORE_KEYWORD_0 フラグを使用して無効にすることができます)。

プロバイダー グループを有効にすることを示すには、EnableParametersEnableProperty メンバーの フラグを使用EVENT_ENABLE_PROPERTY_PROVIDER_GROUPします。

EnableTraceEx2 を呼び出すと、プロバイダーが登録されている場合と登録されていない場合があります。 プロバイダーが既に登録されている場合、ETW はプロバイダーのコールバック関数 (存在する場合) を呼び出し、セッションでイベントの受信を開始します。 プロバイダーがまだ登録されていない場合、ETW はプロバイダーの登録直後にプロバイダーのコールバック関数 (存在する場合) を呼び出し、セッションはイベントの受信を開始します。 プロバイダーがまだ登録されていない場合、プロバイダーのコールバック関数はソース ID を受け取りません。

プロバイダーが登録され、セッションに対して既に有効になっている場合は、EnableTraceEx2 をもう一度呼び出して、LevelMatchAnyKeywordMatchAllKeyword パラメーター、および EnableParametersEnableProperty メンバーと EnableFilterDesc メンバーを更新できます。

Windows 8.1、Windows Server 2012 R2 以降では、イベント ペイロード、スコープ、スタック ウォーク フィルターを EnableTraceEx2 関数とENABLE_TRACE_PARAMETERSおよびEVENT_FILTER_DESCRIPTOR構造体で使用して、ロガー セッション内の特定の条件をフィルター処理できます。 イベント ペイロード フィルターの詳細については、 TdhCreatePayloadFilter 関数と TdhAggregatePayloadFilters 関数と 、ENABLE_TRACE_PARAMETERSEVENT_FILTER_DESCRIPTORおよび PAYLOAD_FILTER_PREDICATE 構造体に関するページを参照してください。

EnableTraceEx2 では、特殊なシステム トレース プロバイダー イベントを有効または無効にできません。 これらは、トレースが StartTrace によって最初に開始されたときに、EVENT_TRACE_PROPERTIESEnableFlags フィールドを介してのみ有効にすることができます。

Windows 11以降、システム トレース プロバイダー イベントは EnableTraceEx2 を使用して有効にすることができます

最大 8 つのトレース セッションで、同じモダン (マニフェスト ベース または トレース ログ) プロバイダーからイベントを有効にして受信できます。 ただし、レガシ (MOF、TMF ベースの WPP) プロバイダーを有効にできるトレース セッションは 1 つだけです。 複数のセッションでレガシ プロバイダーを有効にしようとすると、2 番目のセッションで同じプロバイダーが有効になると、最初のセッションはイベントの受信を停止します。 たとえば、セッション A がレガシ プロバイダーを有効にし、セッション B が同じプロバイダーを有効にした場合、セッション B だけがそのプロバイダーからイベントを受信します。

プロバイダーは、セッションによってプロバイダーが無効になるまで、セッションに対して有効なままになります。 プロバイダーを無効にせずにセッションを開始したアプリケーションが終了した場合、プロバイダーは有効のままです。

マニフェスト ベースのプロバイダーを有効にするために使用されるレベルとキーワードを確認するには、次のいずれかのコマンドを使用します。

  • logman クエリ プロバイダー provider-name
  • wevtutil gp provider-name

従来のプロバイダーの場合、重要度レベルを文書化して潜在的なコントローラーで使用できるようにするか、サポートされているフラグを有効にするかは、プロバイダーにかかっています。 プロバイダーを任意のコントローラーで有効にする場合、プロバイダーは重大度レベルで 0 を受け入れ、フラグを有効にし、既定のログ記録を実行する要求として 0 を解釈する必要があります (何でもかまいません)。

EnableTraceEx2 を使用してクラシック プロバイダーを有効にすると、次の変換が行われます。

  • Level パラメーターは、EnableTraceEnableLevel パラメーターを設定する場合と同じです。
  • MatchAnyKeywordEnableTraceEnableFlag パラメーターを設定する場合と同じですが、キーワード (keyword)値が 64 ビット値から 32 ビット値に切り捨てられる点が異なります。
  • ControlCallback コールバックでは、プロバイダーは GetTraceEnableLevel を呼び出してレベルを取得し、GetTraceEnableFlags を呼び出して有効フラグを取得できます。
  • もう 1 つのパラメーターは使用されません。

次の例では、TdhCreatePayloadFilter 関数と TdhAggregatePayloadFilters 関数を使用したペイロード フィルターでの EnableTraceEx2 の使用を示し、ロガー セッション内の特定の条件をフィルター処理します。

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