如何使用 TraceEvent 库捕获进程名称?

How can I capture process names using the TraceEvent library?

我正在使用 TraceEvent library 捕获 ETW 跟踪,但我无法确定导致事件的进程的名称。

这是我目前的情况:

var session = new TraceEventSession(sessionName, null);
session.EnableProvider(MyEventSource.Log.Guid, TraceEventLevel.Informational,
    options: TraceEventOptions.Stacks);
Task.Delay(1000).ContinueWith(t => session.Stop()); // for testing, deal with it (⌐■_■)
var src = new ETWTraceEventSource(sessionName, TraceEventSourceType.Session);
TraceLog.CreateFromSource(src, etlxFile, null);
var log = TraceLog.OpenOrConvert(etlxFile);
var process = log.Events.First().ProcessName;
// breakpoint

当遇到最后的断点时,process""ProcessID 是一个正确的 PID,但这是我能从日志中的进程中找到的唯一有用信息。

我希望进程名称被日志捕获。我做错了什么,还是这个 API 在我的 OS (Windows 7) 上不可用?

我真的相信进程名称没有被 ETW 日志捕获。 Etw 系统事件仅包含进程 ID 字段。尽管 TraceEvent 库将此声明为 TraceEvent 的一部分,但实际上是根据可执行映像文件名和进程 ID 填充的,这对于所有 4 个 TraceEventSource 实现都是不同的。

另一个观察结果是我从来没有能够填充这个(我的 OS 是 Windows 8.1)。

简单的重现是使用 Microsoft TraceEvent Library Samples 包中的 SimpleEventSourceMonitor 示例。

如果您怀疑这是一个问题,那么最好询问其所有者 Vance Morrison 和 Cosmin Radu。

这可以通过启用内核提供程序,然后维护从进程 ID 到进程名称的查找来完成。这是一个粗略的例子 - 没有错误检查,但你明白了。

// create a lookup collection for future use    
var pidToProcessName = new Dictionary<int, string>();

var session = new TraceEventSession(...);
// enable the kernel provider - note!  this most come first
session.EnableKernelProvider(KernelTraceEventParser.Keywords.Process);
...
session.Source.Kernel.ProcessStart += ProcessStart;
session.Source.Dynamic.All += TraceEvent;
...
session.Source.Procces();    


void ProcessStart(ProcessTraceData obj)
{
    if(obj.OpCode == TraceEventOpcode.Start)
    {
        pidToProcessName[obj.ProcessID] = obj.ProcessName;
    }
}

void TraceEvent(TraceEvent obj)
{
    // pull the process name from our lookup
    var processNameOfEvent = pidToProcessName[obj.ProcessID];    
}