0

0

C# NTFS Change Journal C#如何使用变更日志(USN Journal)高效同步文件

月夜之吻

月夜之吻

发布时间:2026-03-12 16:42:14

|

671人浏览过

|

来源于php中文网

原创

DeviceIoControl 是读取 NTFS USN 日志的唯一可靠方式,需用 \?X: 格式打开卷、管理员权限、正确解析 V2/V3 记录结构,并严格校验 USN 断层与资源释放。

c# ntfs change journal c#如何使用变更日志(usn journal)高效同步文件

如何用 DeviceIoControl 读取 NTFS USN 日志

直接调用 Windows API 是唯一可靠方式,.NET 没有封装 USN Journal 的高层接口。你得自己构造 USN_JOURNAL_DATAREAD_USN_JOURNAL_DATA 结构体,再通过 DeviceIoControl 向卷句柄发 FSCTL_READ_USN_JOURNAL 请求。

常见错误是传错卷路径(比如用 C:myfolder 而不是 \\?\C:),或没以管理员权限运行——没有 SE_MANAGE_VOLUME_NAME 权限会直接返回 ERROR_ACCESS_DENIED

  • 必须用 \\?\X: 格式打开卷,CreateFiledwDesiredAccess 至少要含 GENERIC_READFILE_SHARE_READ
  • READ_USN_JOURNAL_DATA.StartUsn 别硬写 0,首次应先调 FSCTL_QUERY_USN_JOURNAL 拿当前最低/最高 USN,否则可能读到陈旧日志甚至报 ERROR_HANDLE_EOF
  • 每次读完要保存 NextUsn,它才是下一次请求的合法 StartUsn;用 UsnJournalID 校验日志是否被清空过

USN_RECORD_V2USN_RECORD_V3 字段怎么解析

NTFS 返回的 USN 记录是变长结构,版本由 RecordLengthMajorVersion 决定。V2(Win7~10)和 V3(Win10 1809+)字段偏移不同,硬按固定 offset 读 FileNameOffsetFileNameLength 会导致乱码或崩溃。

典型现象:文件名显示为一堆问号或中文变成方块,其实是把 V3 的 FileNameOffset 当 V2 解析了(V3 多了 ReasonSourceInfo 字段)。

  • 务必先检查 MajorVersion:V2 是 2,V3 是 3;MinorVersion 可忽略
  • V2 中 FileNameOffset = 64,V3 中是 80FileNameLength 单位是字节,不是字符数,需用 Encoding.Unicode.GetString() 转换
  • Reason 字段值是位掩码,USN_REASON_RENAME_NEW_NAMEUSN_REASON_RENAME_OLD_NAME 会分两条记录出现,别当成两个独立重命名事件

为什么 FSCTL_READ_USN_JOURNAL 突然返回 0 条记录

不是代码错了,大概率是日志被系统回收或手动清空了。USN Journal 有大小上限(默认约 32MB),满后旧记录会被覆盖;管理员执行 fsutil usn deletejournal /d C: 也会清零。

Krea AI
Krea AI

多功能的一站式AI图像生成和编辑平台

下载

错误做法是发现没数据就立刻重试或报错退出。正确响应是查 USN_JOURNAL_DATA.FirstUsn 是否大于上次保存的 LowestValidUsn——如果大,说明中间有断层,只能全量扫描目录补漏。

  • 每次成功读取后,用 USN_JOURNAL_DATA.LowestValidUsn 更新本地 checkpoint,它代表“最早还能读到的有效 USN”
  • 若新查到的 FirstUsn > LastKnownUsn + 1,说明丢失变更,需触发 fallback 扫描(例如用 Directory.EnumerateFiles + FileInfo.LastWriteTimeUtc 对比)
  • 不要依赖 MaximumSize 做预分配缓冲区,实际单次最多返回约 1MB 数据,超了会截断并设 ERROR_MORE_DATA

C# 中怎么安全释放 USN Journal 句柄和内存

卷句柄泄漏会导致后续无法打开同一卷,而未 Marshal.FreeHGlobal 的 USN 缓冲区会引发内存持续增长。这不是 GC 能自动收拾的问题。

最常踩的坑是把 Marshal.AllocHGlobal 分配的缓冲区交给异步回调使用,回调里忘了 FreeHGlobal;或者 CloseHandle 调用失败却没检查返回值,句柄实际还在。

  • using var handle = new SafeFileHandle(...) 包裹卷句柄,确保 Dispose() 调用 CloseHandle
  • USN 缓冲区必须显式 Marshal.FreeHGlobal(ptr),且只在确定不再访问该内存后调用(尤其注意多线程场景下指针是否还在被其他线程读)
  • CloseHandle 前确认所有 DeviceIoControl 调用已完成,否则可能触发 STATUS_INVALID_HANDLE

USN Journal 不是开箱即用的同步方案,它省的是遍历时间,但换来了对卷状态、权限、版本兼容性的强依赖。漏掉任意一个 checkpoint 校验或权限检查,同步就会无声地出错。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

490

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

202

2025.07.04

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1925

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

656

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2395

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

47

2026.01.19

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

443

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

605

2023.08.10

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 11.1万人学习

C 教程
C 教程

共75课时 | 5.4万人学习

C++教程
C++教程

共115课时 | 21.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号