不能直接用readdirectorychangesw监控整个磁盘根目录,因其不支持卷级递归,需先安全遍历可读子目录并为每个目录单独创建监控句柄;更可靠方案是启用并解析usn journal实现无遗漏卷级捕获。

用 ReadDirectoryChangesW 监控整个磁盘?别这么干
直接调用 ReadDirectoryChangesW 监控 C:\ 根目录,系统会拒绝——它不支持对卷根目录的递归监控,且会因子目录过多(如 System Volume Information、$Recycle.Bin)频繁返回 ERROR_ACCESS_DENIED 或 ERROR_NOTIFY_ENUM_DIR。更关键的是,该 API 本身不递归,你得自己遍历所有子目录并为每个句柄单独调用,极易漏事件、爆句柄数、卡主线程。
必须分层:先枚举路径,再为每个可访问目录创建独立监控句柄
Windows 文件变更通知本质是“目录级”而非“卷级”。要覆盖整个磁盘,唯一可行路径是:先安全遍历所有可读子目录,跳过权限不足或系统保留路径,再为每个有效目录分配独立的 OVERLAPPED + ReadDirectoryChangesW 实例。这不是懒人方案,而是 Win32 的硬性约束。
- 用
FindFirstVolumeW/FindNextVolumeW获取卷名(如\\?\C:\),再用GetVolumePathNamesForVolumeNameW转成挂载点(如C:\) - 用
FindFirstFileExW遍历C:\*,过滤掉FILE_ATTRIBUTE_REPARSE_POINT(符号链接/挂载点)和FILE_ATTRIBUTE_SYSTEM目录(如System Volume Information) - 对每个候选目录,先用
CreateFileW尝试以GENERIC_READ打开,失败则跳过;成功则立即调用ReadDirectoryChangesW并绑定 I/O 完成端口或线程池回调 - 每个目录需独立
HANDLE和缓冲区(建议 ≥ 64KB),避免事件混杂;缓冲区满时事件丢失不可恢复,必须及时处理
权限与稳定性陷阱:管理员权限 ≠ 万事大吉
即使以管理员身份运行,仍会遇到三类硬拦截:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
-
\?GlobalRootDeviceHarddiskVolumeShadowCopy*类快照目录:CreateFileW返回ERROR_ACCESS_DENIED,必须跳过 - BitLocker 加密卷的未解锁状态:
ReadDirectoryChangesW立即失败,错误码常为ERROR_INVALID_PARAMETER,需在打开前用GetVolumeInformationByHandleW检查dwFlags & FILE_VOLUME_IS_ENCRYPTED - NTFS 硬链接目标目录:若多个目录指向同一 MFT 记录,监控会重复触发;无法自动去重,需在回调中比对
BY_HANDLE_FILE_INFORMATION.nFileIndexLow/High去重
替代方案:用 USN Journal 实现真正卷级变更捕获
如果必须“深度”覆盖全盘(包括被跳过的系统目录、硬链接、重定向),ReadDirectoryChangesW 是伪命题。USN Journal(Update Sequence Number Journal)才是 Windows 原生支持的卷级变更日志机制,但代价是:必须开启卷的 USN 日志(FSCTL_CREATE_USN_JOURNAL)、解析二进制流、维护 USN 值游标、处理日志满回绕。它不实时,但无遗漏。
典型流程:CreateFileW 打开卷(如 \\?\C:)→ DeviceIoControl 发送 FSCTL_QUERY_USN_JOURNAL 获取当前日志范围 → 启动循环:用 FSCTL_READ_USN_JOURNAL 拉取增量记录 → 解析 USN_RECORD_V3 结构体中的 FileNameOffset 和 FileNameLength 提取路径 → 更新 StartUsn 游标。注意:普通用户无法读 USN 日志,必须有 SE_MANAGE_VOLUME_NAME 权限(通常需管理员+显式提权)。
真正的难点不在代码长度,而在如何容忍日志截断、如何将 USN 记录映射回稳定路径(硬链接/重解析点需额外 FSCTL_GET_REPARSE_POINT 查询)、以及如何避免因处理延迟导致日志空间耗尽后整个卷停止记录——这些细节一旦忽略,监控就变成间歇性失明。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










