我正在嘗試收聽ETW內核事件。Windows ETW:內核使用者未收到EventCallback或BufferCallback事件
第1步:調用
OpenTrace
,指定EventCallback
和可選BufferCallback
功能,將我的電話時被要求ProcessTrace
: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();
第2步:Enable kernel events。這通過呼叫
StartTrace
完成。在我來說,我想跟蹤內核interrupts(EVENT_TRACE_FLAG_INTERRUPT
)和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));
和日誌開始成功地(我可以看到
foo.etl
開始生長至其5 MB circuluar限制)。第3步:呼叫
ProcessTrace
,該塊,直到它已交付的所有等待事件步驟1中指定的EventCallback
處理程序:var res: LongWord; begin res := EventTrace.ProcessTrace(@currentTrace, 1, nil, nil); if (res <> ERROR_SUCCESS) then raise EWin32Error.Create(SysErrorMessage(res));
除ProcessTrace
一再立即返回,也沒有回調稱爲 - 儘管etl文件存在並不斷增長。
如果我改變從基於文件的到實時日誌記錄:
第1步 -
OpenTrace
更改,以支持實時:logFile.ProcessTraceMode := PROCESS_TRACE_MODE_REAL_TIME;
步驟2 -
StartTrace
和變革,以支持實時:sessionProperties.LogFileMode := EVENT_TRACE_REAL_TIME_MODE;
在這種情況下ProcessTrace
從未的回報,但也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;
根據我的經驗(至少在實時跟蹤中),即使會話不存在,OpenTrace()也總是「成功」。只有當您調用ProcessTrace()時,它纔會失敗,並返回ERROR_WMI_INSTANCE_NOT_FOUND。我不知道內核提供者的行爲如何,但是使用自定義實時提供者需要在OpenTrace()之前啓動StartTrace()。我認爲將事件跟蹤到文件時也是如此。 – Luke 2012-01-30 14:55:29