C++中ETW跟踪会话启动失败(错误码87)及事件打印求助
错误:无法在C++中启动ETW跟踪会话(错误码87)
开发C++应用时,使用Event Tracing for Windows (ETW)实时消费并打印事件,启动跟踪和注册提供程序时遇到以下错误:
unable to start trace 87
unable to register provider 87
错误码87对应ERROR_INVALID_PARAMETER,以下是问题代码片段:
#pragma once #include <windows.h> #include <evntrace.h> #include <evntcons.h> #include <iostream> #include <thread> class EventProvider { private: TRACEHANDLE sessionhandle; TRACEHANDLE consumertrace; GUID eventprovider; LPCWSTR sessionname; PEVENT_TRACE_PROPERTIES properties; bool running; public: EventProvider(LPCWSTR, GUID); void initProperty(); void startTrace(); void consumer(); static void run(PTRACEHANDLE); static VOID WINAPI eventcallback(PEVENT_RECORD); ~EventProvider(); }; EventProvider::EventProvider(LPCWSTR sessionname, GUID provider) : sessionhandle(0), consumertrace(0), eventprovider(provider), sessionname(sessionname), properties(nullptr), running(false) { this->initProperty(); this->startTrace(); this->consumer(); } void EventProvider::initProperty() { ULONG buffsize = sizeof(EVENT_TRACE_PROPERTIES) + 2 * sizeof(WCHAR) * 1024; this->properties = (EVENT_TRACE_PROPERTIES*)malloc(buffsize); if (this->properties == NULL) { std::cout << "Unable to allocate bytes for properties" << std::endl; } ZeroMemory(this->properties, buffsize); this->properties->Wnode.BufferSize = buffsize; this->properties->Wnode.Guid = this->eventprovider; this->properties->Wnode.Flags = WNODE_FLAG_TRACED_GUID; this->properties->LogFileMode = EVENT_TRACE_REAL_TIME_MODE; this->properties->Wnode.ClientContext = 1; this->properties->LogFileNameOffset = 0; this->properties->EnableFlags = EVENT_TRACE_FLAG_PROCESS; this->properties->BufferSize = 64; // Size of each tracing buffer in KB this->properties->MinimumBuffers = 1; this->properties->MaximumBuffers = 5; this->properties->MaximumFileSize = 0; } VOID WINAPI EventProvider::eventcallback(PEVENT_RECORD pevent) { std::cout << "i have bbencalled" << std::endl; } void EventProvider::startTrace() { DWORD status = StartTraceW((PTRACEHANDLE)sessionhandle, sessionname, properties); if (status != ERROR_SUCCESS) { std::cout << "unable to start trace " << GetLastError() << std::endl; } DWORD status2 = EnableTraceEx2(this->sessionhandle, &this->eventprovider, EVENT_CONTROL_CODE_ENABLE_PROVIDER, TRACE_LEVEL_INFORMATION, 0, 0, 0, NULL); if (status != ERROR_SUCCESS) { std::cout << "unable to register provider " << GetLastError() << std::endl; } } void EventProvider::run(PTRACEHANDLE handel) { if (ProcessTrace(handel, 1, 0, 0) != ERROR_SUCCESS) { exit(0); } } void EventProvider::consumer() { EVENT_TRACE_LOGFILEW trace; TRACE_LOGFILE_HEADER* pheader = &trace.LogfileHeader; ZeroMemory(&trace, sizeof(EVENT_TRACE_LOGFILEW)); trace.ProcessTraceMode = PROCESS_TRACE_MODE_REAL_TIME | PROCESS_TRACE_MODE_EVENT_RECORD; trace.EventRecordCallback = (PEVENT_RECORD_CALLBACK)(EventProvider::eventcallback); trace.LoggerName = (LPWSTR)R"(ANTI TRACER)"; TRACEHANDLE handle = OpenTraceW((PEVENT_TRACE_LOGFILEW)&trace); if (handle == INVALID_PROCESSTRACE_HANDLE) { std::cout << "Unable start trace session : " << GetLastError() << std::endl; } consumertrace = (TRACEHANDLE)handle; std::thread thread(run, (PTRACEHANDLE)consumertrace); }
问题定位与修复方案
以下是导致错误码87的核心问题及修复:
- StartTraceW参数错误:第一个参数需要传入
TRACEHANDLE*类型(用于接收会话句柄),原代码直接将初始值为0的sessionhandle强制转换为指针,参数无效。应改为传入&sessionhandle。 - EVENT_TRACE_PROPERTIES的GUID设置错误:跟踪会话的
Wnode.Guid必须设置为SystemTraceControlGuid,目标提供程序的GUID仅在EnableTraceEx2中指定,原代码错误将提供程序GUID赋值给会话。 - EnableTraceEx2错误判断逻辑错误:原代码用
StartTraceW的返回值status判断EnableTraceEx2的结果,应改为判断status2。 - 消费端会话名不匹配:启动会话时使用构造函数传入的
sessionname,但消费时硬编码了R"(ANTI TRACER)",需保持名称一致。 - ProcessTrace参数错误:第一个参数是
TRACEHANDLE数组的指针,原代码传入单个句柄指针,需改为传入包含句柄的数组地址。 - 线程生命周期问题:消费线程是局部变量,会立即销毁,需用成员变量保存线程对象,并在析构时正确回收。
修复后的完整代码:
#pragma once #include <windows.h> #include <evntrace.h> #include <evntcons.h> #include <iostream> #include <thread> class EventProvider { private: TRACEHANDLE sessionhandle; TRACEHANDLE consumertrace; GUID eventprovider; LPCWSTR sessionname; PEVENT_TRACE_PROPERTIES properties; bool running; std::thread consumerThread; // 保存消费线程 public: EventProvider(LPCWSTR, GUID); void initProperty(); void startTrace(); void consumer(); static void run(TRACEHANDLE*); static VOID WINAPI eventcallback(PEVENT_RECORD); ~EventProvider(); }; EventProvider::EventProvider(LPCWSTR sessionname, GUID provider) : sessionhandle(0), consumertrace(INVALID_PROCESSTRACE_HANDLE), eventprovider(provider), sessionname(sessionname), properties(nullptr), running(false) { this->initProperty(); this->startTrace(); this->consumer(); } void EventProvider::initProperty() { ULONG buffsize = sizeof(EVENT_TRACE_PROPERTIES) + 2 * sizeof(WCHAR) * 1024; this->properties = (EVENT_TRACE_PROPERTIES*)malloc(buffsize); if (this->properties == NULL) { std::cout << "Unable to allocate bytes for properties" << std::endl; return; } ZeroMemory(this->properties, buffsize); this->properties->Wnode.BufferSize = buffsize; this->properties->Wnode.Guid = SystemTraceControlGuid; // 修正会话GUID this->properties->Wnode.Flags = WNODE_FLAG_TRACED_GUID; this->properties->LogFileMode = EVENT_TRACE_REAL_TIME_MODE; this->properties->Wnode.ClientContext = 1; this->properties->LogFileNameOffset = 0; this->properties->EnableFlags = EVENT_TRACE_FLAG_PROCESS; this->properties->BufferSize = 64; this->properties->MinimumBuffers = 1; this->properties->MaximumBuffers = 5; this->properties->MaximumFileSize = 0; } VOID WINAPI EventProvider::eventcallback(PEVENT_RECORD pevent) { std::cout << "事件已触发" << std::endl; } void EventProvider::startTrace() { DWORD status = StartTraceW(&sessionhandle, sessionname, properties); // 传入句柄指针 if (status != ERROR_SUCCESS) { std::cout << "unable to start trace " << status << std::endl; return; } DWORD status2 = EnableTraceEx2(this->sessionhandle, &this->eventprovider, EVENT_CONTROL_CODE_ENABLE_PROVIDER, TRACE_LEVEL_INFORMATION, 0, 0, 0, NULL); if (status2 != ERROR_SUCCESS) { // 修正判断条件 std::cout << "unable to register provider " << status2 << std::endl; } } void EventProvider::run(TRACEHANDLE* handles) { if (ProcessTrace(handles, 1, NULL, NULL) != ERROR_SUCCESS) { std::cout << "ProcessTrace failed: " << GetLastError() << std::endl; } } void EventProvider::consumer() { EVENT_TRACE_LOGFILEW trace; ZeroMemory(&trace, sizeof(EVENT_TRACE_LOGFILEW)); trace.ProcessTraceMode = PROCESS_TRACE_MODE_REAL_TIME | PROCESS_TRACE_MODE_EVENT_RECORD; trace.EventRecordCallback = EventProvider::eventcallback; trace.LoggerName = const_cast<LPWSTR>(sessionname); // 使用一致的会话名 TRACEHANDLE handle = OpenTraceW(&trace); if (handle == INVALID_PROCESSTRACE_HANDLE) { std::cout << "Unable start trace session : " << GetLastError() << std::endl; return; } consumertrace = handle; TRACEHANDLE handles[] = {consumertrace}; consumerThread = std::thread(run, handles); // 保存线程对象 } EventProvider::~EventProvider() { // 清理资源 if (consumertrace != INVALID_PROCESSTRACE_HANDLE) { CloseTrace(consumertrace); } if (sessionhandle != 0) { ControlTraceW(sessionhandle, sessionname, properties, EVENT_TRACE_CONTROL_STOP); } if (properties != nullptr) { free(properties); } if (consumerThread.joinable()) { consumerThread.join(); } }
内容的提问来源于stack exchange,提问作者90_Priyanshu kumar Singh
相关产品推荐
相关产品推荐

