Windows ETW:内核使用者未收到 EventCallback 或 BufferCallback 事件
我正在尝试监听 ETW 内核事件。
第 1 步:调用
<前><代码>变量 日志文件:EVENT_TRACE_LOGFILE; 当前跟踪:TRACEHANDLE; 开始 ZeroMemory(@logFile, sizeof(logFile)); logFile.LoggerName := KERNEL_LOGGER_NAME; logFile.LogFileName := 'C:\Users\Ian\foo.etl'; logFile.ProcessTraceMode := 0; logFile.EventCallback := RealtimeEventCallback; logFile.BufferCallback := BufferCallback; //选修的 当前Trace := OpenTrace(@logFile); 如果 (currentTrace = INVALID_PROCESSTRACE_HANDLE) 或 (currentTrace = -1) 那么 引发LastWin32Error();OpenTrace
,指定EventCallback
< /a> 和可选的BufferCallback
< /a> 在我调用ProcessTrace
< /a>:第 2 步:启用内核事件。这是通过调用
<前><代码>变量 会话属性:PEVENT_TRACE_PROPERTIES; 缓冲区大小:Int64; th:跟踪句柄; 记录器名称:字符串; 日志文件路径:字符串; 开始 loggerName := KERNEL_LOGGER_NAME; logFilePath := 'C:\Users\Ian\foo.etl'; bufferSize := sizeof(EVENT_TRACE_PROPERTIES) + 1024 //会话名称最大长度为1024个字符 + 1024; //日志文件名最大长度为1024个字符 sessionProperties := AllocMem(bufferSize); ZeroMemory(sessionProperties, bufferSize); sessionProperties.Wnode.BufferSize := bufferSize; sessionProperties.Wnode.ClientContext := 1; //QPC时钟分辨率 sessionProperties.Wnode.Flags := WNODE_FLAG_TRACED_GUID; sessionProperties.Wnode.Guid := SystemTraceControlGuid; sessionProperties.EnableFlags := EVENT_TRACE_FLAG_INTERRUPT 或 EVENT_TRACE_FLAG_DPC; sessionProperties.LogFileMode := EVENT_TRACE_FILE_MODE_CIRCULAR; sessionProperties.MaximumFileSize := 5; // 5MB sessionProperties.LoggerNameOffset := sizeof(EVENT_TRACE_PROPERTIES); sessionProperties.LogFileNameOffset := sizeof(EVENT_TRACE_PROPERTIES)+1024; //复制LoggerName到偏移地址 MoveMemory(指针(Cardinal(sessionProperties)+sessionProperties.LoggerNameOffset), PChar(loggerName), Length(loggerName)+1); //复制LogFilePath到偏移地址 MoveMemory(指针(Cardinal(sessionProperties)+sessionProperties.LogFileNameOffset), PChar(logFilePath), Length(logFilePath)+1); hr := StartTrace({var}th, PChar(loggerName), sessionProperties); if (hr <> ERROR_SUCCESS) then 引发 EWin32Error.Create(SysErrorMessage(hr));开始跟踪
。就我而言,我想跟踪内核 中断 (EVENT_TRACE_FLAG_INTERRUPT
< /a>) 和 延迟过程调用 (<一个href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa363784%28v=vs.85%29.aspx" rel="nofollow">EVENT_TRACE_FLAG_DPC
< /a>):日志已成功启动(我可以看到
foo.etl
开始增长到其 5 MB 循环限制)。第 3 步:调用
<前><代码>变量 res:长字; 开始 res := EventTrace.ProcessTrace(@currentTrace, 1, nil, nil); if (res <> ERROR_SUCCESS) then 引发 EWin32Error.Create(SysErrorMessage(res));ProcessTrace
,它会阻塞,直到将所有待处理事件传递到EventCallback
< /a> 步骤 1 中指定的处理程序:
除了 ProcessTrace
立即重复返回,并且不调用回调 - 即使 etl 文件存在且不断增长。
如果我将日志记录从基于文件更改为实时日志记录:
第 1 步 -
OpenTrace
更改为支持实时:logFile.ProcessTraceMode := PROCESS_TRACE_MODE_REAL_TIME;
第 2 步 -
StartTrace
进行更改以支持 >实时:sessionProperties.LogFileMode := EVENT_TRACE_REAL_TIME_MODE;
在本例中 ProcessTrace
从不< /em> 返回,但 EventCallback
或 BufferCallback
都没有被调用。
我做错了什么?
更新:我的回调函数:
function BufferCallback(Logfile: PEVENT_TRACE_LOGFILE): LongWord; stdcall;
begin
ShowMessage('BufferCallback');
Result := 1; //return true to keep processing rows
end;
procedure RealtimeEventCallback(pEvent: PEVENT_TRACE); stdcall;
begin
ShowMessage('EventCallback');
nEvents := nEvents+1;
end;
i am trying to listen to ETW kernel events.
Step 1: Call
OpenTrace
, specifying theEventCallback
and optionalBufferCallback
functions that will be called during my call toProcessTrace
:var logFile: EVENT_TRACE_LOGFILE; currentTrace: TRACEHANDLE; begin ZeroMemory(@logFile, sizeof(logFile)); logFile.LoggerName := KERNEL_LOGGER_NAME; logFile.LogFileName := 'C:\Users\Ian\foo.etl'; logFile.ProcessTraceMode := 0; logFile.EventCallback := RealtimeEventCallback; logFile.BufferCallback := BufferCallback; //optional currentTrace := OpenTrace(@logFile); if (currentTrace = INVALID_PROCESSTRACE_HANDLE) or (currentTrace = -1) then RaiseLastWin32Error();
Step 2: Enable kernel events. This is done by calling
StartTrace
. In my case i want to trace kernel interrupts (EVENT_TRACE_FLAG_INTERRUPT
) and deferred procedure calls (EVENT_TRACE_FLAG_DPC
):var sessionProperties: PEVENT_TRACE_PROPERTIES; bufferSize: Int64; th: TRACEHANDLE; loggerName: string; logFilePath: string; begin loggerName := KERNEL_LOGGER_NAME; logFilePath := 'C:\Users\Ian\foo.etl'; bufferSize := sizeof(EVENT_TRACE_PROPERTIES) + 1024 //maximum session name is 1024 characters + 1024; //maximum log file name is 1024 characters sessionProperties := AllocMem(bufferSize); ZeroMemory(sessionProperties, bufferSize); sessionProperties.Wnode.BufferSize := bufferSize; sessionProperties.Wnode.ClientContext := 1; //QPC clock resolution sessionProperties.Wnode.Flags := WNODE_FLAG_TRACED_GUID; sessionProperties.Wnode.Guid := SystemTraceControlGuid; sessionProperties.EnableFlags := EVENT_TRACE_FLAG_INTERRUPT or EVENT_TRACE_FLAG_DPC; sessionProperties.LogFileMode := EVENT_TRACE_FILE_MODE_CIRCULAR; sessionProperties.MaximumFileSize := 5; // 5 MB sessionProperties.LoggerNameOffset := sizeof(EVENT_TRACE_PROPERTIES); sessionProperties.LogFileNameOffset := sizeof(EVENT_TRACE_PROPERTIES)+1024; //Copy LoggerName to the offset address MoveMemory(Pointer(Cardinal(sessionProperties)+sessionProperties.LoggerNameOffset), PChar(loggerName), Length(loggerName)+1); //Copy LogFilePath to the offset address MoveMemory(Pointer(Cardinal(sessionProperties)+sessionProperties.LogFileNameOffset), PChar(logFilePath), Length(logFilePath)+1); hr := StartTrace({var}th, PChar(loggerName), sessionProperties); if (hr <> ERROR_SUCCESS) then raise EWin32Error.Create(SysErrorMessage(hr));
And the log is started sucessfully (i can see
foo.etl
begin to grow to its 5 MB circuluar limit).Step 3: Call
ProcessTrace
, which blocks until it has delivered all pending events to theEventCallback
handler specified in Step 1:var res: LongWord; begin res := EventTrace.ProcessTrace(@currentTrace, 1, nil, nil); if (res <> ERROR_SUCCESS) then raise EWin32Error.Create(SysErrorMessage(res));
Except that ProcessTrace
repeatedly returns immediately, and no callback is called - even though the etl file is present and growing.
If i change the logging from File Based to Realtime logging:
Step 1 -
OpenTrace
changes to support realtime:logFile.ProcessTraceMode := PROCESS_TRACE_MODE_REAL_TIME;
Step 2 -
StartTrace
changes to support realtime:sessionProperties.LogFileMode := EVENT_TRACE_REAL_TIME_MODE;
In this case ProcessTrace
never returns, but neither EventCallback
or BufferCallback
are ever called.
What am i doing wrong?
Update: My callback functions:
function BufferCallback(Logfile: PEVENT_TRACE_LOGFILE): LongWord; stdcall;
begin
ShowMessage('BufferCallback');
Result := 1; //return true to keep processing rows
end;
procedure RealtimeEventCallback(pEvent: PEVENT_TRACE); stdcall;
begin
ShowMessage('EventCallback');
nEvents := nEvents+1;
end;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我发现了问题。
我使用的标题不是四字对齐的。
在 Delphi 的说法中,使用了关键字
packed
。i found the problem.
The headers i was using were not quad-word aligned.
In Delphi parlance, the keyword
packed
was being used.您不能同时提供 LoggerName 和 LogFileName。如果您提供 LoggerName,则 LogFileName 必须为 null。请参阅此链接。
You can't provide both LoggerName and LogFileName. If you supply a LoggerName, LogFileName must be null. See this link.