使用TraceEvent监控特定文件CloseFile操作失效问题排查求助
问题描述
我需要监控某个特定文件的CloseFile操作并触发相应动作。用ProcMon能看到该文件被频繁查询和读取,但使用Microsoft.Diagnostics.Tracing.TraceEvent NuGet包实现时,功能随机失效,近期完全无法捕获目标文件的关闭事件。已确认以下情况:
- IDE以管理员权限运行
- 已关闭ProcMon避免干扰
- 回调函数可正常执行(能捕获大量其他文件名,但无法捕获目标文件)
- 已将关键字设置为
All(使用FileIO关键字时完全无效) - 回调返回的
LostEvents数值始终为0
我的代码如下:
await Task.Run(() => { using TraceEventSession session = new("MySession"); session.EnableKernelProvider(KernelTraceEventParser.Keywords.All); session.Source.Kernel.FileIOClose+= data => { if (data.FileName == @"c:\foo.txt") { // do stuff } }; session.Source.Process(); });
问题分析与解决
核心问题1:路径匹配逻辑不严谨
Windows文件路径不区分大小写,且FileIOClose事件返回的FileName可能存在格式差异(比如全大写盘符、规范化后的路径格式等),直接用==做精确匹配会导致漏判。
核心问题2:关键字启用方式不当
直接使用Keywords.All会引入大量无关事件,可能分散事件处理资源;单独用FileIO关键字无效,是因为需要同时启用FileIOInit关键字才能捕获完整的文件IO事件链。
修复后的代码
await Task.Run(() => { using var session = new TraceEventSession("MySession"); // 明确启用文件IO相关关键字,过滤无关事件 session.EnableKernelProvider( KernelTraceEventParser.Keywords.FileIO | KernelTraceEventParser.Keywords.FileIOInit, TraceEventLevel.Informational); session.Source.Kernel.FileIOClose += data => { // 用路径规范化+不区分大小写的方式做匹配 var targetPath = Path.GetFullPath(@"c:\foo.txt"); var eventPath = Path.GetFullPath(data.FileName); if (Path.Equals(eventPath, targetPath, StringComparison.OrdinalIgnoreCase)) { // do stuff } }; session.Source.Process(); });
额外排查建议
- 在回调中临时添加
Console.WriteLine(data.FileName),输出所有捕获到的文件路径,确认目标文件的实际格式是否和预期一致。 - 若仍无法捕获,可尝试监听
FileIOCloseFile事件(部分场景下该事件比FileIOClose更精准)。
内容的提问来源于stack exchange,提问作者boop
相关产品推荐
相关产品推荐

