Windows系统文件IO读写事件实时监控方案咨询
解决方案:Windows文件读写事件监控(Java环境)
方案一:PowerShell+ETW 轻量实现(无需编写原生代码)
Windows ETW(Event Tracing for Windows)是系统内置的事件追踪机制,可捕获文件IO读写事件,无需驱动。我们可以用PowerShell启动ETW会话,输出结构化日志,再通过Java解析其标准输出实现实时监控。
步骤1:PowerShell脚本实现ETW捕获
编写脚本FileIOMonitor.ps1,仅捕获读写事件并输出关键字段:
# 创建ETW会话,仅捕获FileIO的Read/Write事件 $sessionName = "FileIORawMonitor" $providerName = "Microsoft-Windows-FileIO" # 停止已有同名会话 wevtutil sl $sessionName /e:false 2>&1 | Out-Null wevtutil cl $sessionName 2>&1 | Out-Null # 启动会话,输出JSON格式的事件(包含文件名、字节数、偏移量) wevtutil sl $sessionName /e:true /q:"*[System[Provider[@Name='$providerName'] and (EventID=3 or EventID=4)]]" /f:json
- 事件ID3对应读操作,ID4对应写操作
- 输出的JSON中,
UserData.FileIoRead/UserData.FileIoWrite包含核心字段:FileName:完整文件路径IrpInfo.ByteOffset:文件内读写起始位置IrpInfo.Length:读写字节数
步骤2:Java解析PowerShell输出
在Java中启动PowerShell进程,读取其标准输出并实时解析JSON:
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.BufferedReader; import java.io.InputStreamReader; public class FileIOMonitor { public static void main(String[] args) throws Exception { // 启动PowerShell进程执行监控脚本 Process process = new ProcessBuilder("powershell.exe", "-ExecutionPolicy", "Bypass", "-File", "FileIOMonitor.ps1") .redirectErrorStream(true) .start(); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); ObjectMapper mapper = new ObjectMapper(); String line; // 实时读取并解析输出 while ((line = reader.readLine()) != null) { try { JsonNode event = mapper.readTree(line); JsonNode userData = event.get("UserData"); if (userData == null) continue; String eventType = userData.fieldNames().next(); JsonNode ioData = userData.get(eventType); String fileName = ioData.get("FileName").asText(); long offset = ioData.get("IrpInfo").get("ByteOffset").asLong(); long bytes = ioData.get("IrpInfo").get("Length").asLong(); // 输出或处理监控数据 System.out.printf("%s | 文件: %s | 偏移量: %d | 字节数: %d%n", eventType.equals("FileIoRead") ? "读操作" : "写操作", fileName, offset, bytes); } catch (Exception e) { // 忽略非JSON格式的系统提示行 continue; } } } }
- 依赖Jackson库解析JSON,可通过Maven引入:
com.fasterxml.jackson.core:jackson-databind:2.15.2 - 需通过
-ExecutionPolicy Bypass确保PowerShell允许运行脚本
方案二:JNI调用Windows ETW API(原生集成)
如果不想依赖PowerShell,可通过JNI直接调用Windows ETW用户态API,注册事件回调获取实时数据,全程无需编写内核驱动。
核心思路
- 编写C++代码,注册
Microsoft-Windows-FileIO提供者,过滤Read/Write事件; - 在C++回调中提取文件名、偏移量、字节数,传递给Java;
- Java通过JNI加载原生库,接收实时事件。
简化的C++代码片段(JNI部分)
#include <windows.h> #include <evntrace.h> #include <jni.h> #include "FileIOMonitorJNI.h" JavaVM* g_jvm; // 事件回调函数 VOID WINAPI EventCallback(PEVENT_RECORD pEventRecord) { if (pEventRecord->EventHeader.EventID != 3 && pEventRecord->EventID != 4) return; // 解析事件数据(需参考Microsoft-Windows-FileIO的事件schema实现) const char* fileName = "..."; // 提取文件名 long long offset = ...; // 提取读写偏移量 long long bytes = ...; // 提取读写字节数 // 调用Java方法传递监控数据 JNIEnv* env; g_jvm->AttachCurrentThread((void**)&env, NULL); jclass cls = env->FindClass("com/example/FileIOMonitor"); jmethodID mid = env->GetStaticMethodID(cls, "onFileIOEvent", "(Ljava/lang/String;JJ)V"); jstring jFileName = env->NewStringUTF(fileName); env->CallStaticVoidMethod(cls, mid, jFileName, offset, bytes); env->DeleteLocalRef(jFileName); g_jvm->DetachCurrentThread(); } // JNI初始化方法 JNIEXPORT void JNICALL Java_com_example_FileIOMonitor_startMonitoring(JNIEnv* env, jclass cls) { env->GetJavaVM(&g_jvm); // 初始化ETW会话、注册提供者、启动追踪(具体实现参考Windows ETW API文档) }
Java对应代码
public class FileIOMonitor { static { System.loadLibrary("FileIOMonitorJNI"); } public static native void startMonitoring(); public static void onFileIOEvent(String fileName, long offset, long bytes) { // 处理实时监控事件 System.out.printf("文件: %s | 偏移量: %d | 字节数: %d%n", fileName, offset, bytes); } public static void main(String[] args) { startMonitoring(); // 保持进程运行 while (true) { try { Thread.sleep(1000); } catch (InterruptedException e) {} } } }
- 事件结构可通过
wevtutil gp Microsoft-Windows-FileIO /e查看 - 需依赖Windows SDK和C++编译环境
方案对比
| 方案 | 复杂度 | 依赖 | 实时性 |
|---|---|---|---|
| PowerShell+ETW | 低 | PowerShell、Jackson | 秒级延迟(符合需求) |
| JNI+ETW API | 中 | C++编译环境、Windows SDK | 亚秒级延迟 |
注意事项
- 两种方案均需管理员权限运行,因为ETW系统级事件需要权限
- 可通过ETW查询语句进一步过滤事件(如排除特定路径)
- 已通过EventID过滤创建/删除事件,无需额外处理
内容的提问来源于stack exchange,提问作者JayC667
相关产品推荐
相关产品推荐

