跳转到主内容
极星编程网:以代码为星,赴技术山海!

c++怎么在Windows下利用CreateFile独占式打开并锁定文件【实战】

CreateFile返回INVALID_HANDLE_VALUE却无显式错误,通常因ERROR_SHARING_VIOLATION——文件被其他进程以不兼容共享模式打开;必须设dwShareMode=0、dwCreationDisposition为OPEN_EXISTING或CREATE_ALWAYS、hTemplateFile为NULL,且确保无残留句柄。 为什么
CreateFile
返回
INVALID_HANDLE_VALUE
却没报错? 常见现象是调用后直接失败,
GetLastError()
返回
ERROR_SHARING_VIOLATION
——这说明文件正被其他进程(甚至同一进程的另一处代码)以不兼容的共享模式打开。 独占式打开的关键不是“加锁”,而是从打开那一刻起就拒绝所有其他访问。必须显式设置
dwShareMode = 0
,即禁止任何共享。
dwShareMode = 0
是硬性要求,哪怕只是想读取也不能设
FILE_SHARE_READ
如果文件已由
fopen
、
std::fstream
或其他
CreateFile
实例打开过,当前调用必败 注意:Explorer.exe 有时会因缩略图/属性面板临时打开文件,导致看似“空闲”的文件实际被占用
LockFileEx
和
CreateFile
的独占逻辑区别在哪?
CreateFile
的独占是“打开级”的,靠系统内核在句柄创建时拦截;
LockFileEx
是“内容级”的,作用于已打开句柄的某段字节范围,且不阻止别人重新
CreateFile
—— 它俩解决的是不同层次的问题。 只想要“整个文件不让别人碰”,就别调
LockFileEx
,老老实实设
dwShareMode = 0
并确保无残留句柄
LockFileEx
需要先有有效句柄,且锁定区域可能被其他进程绕过(比如对方也用
CreateFile(..., 0, ...)
强行打开) 若需跨进程协作式互斥,
CreateMutex
比文件锁更可靠;文件锁更适合防止意外覆盖 实际写法中容易漏掉的三个参数细节 光设
dwShareMode = 0
不够,这三个参数配合错误,照样拿不到独占句柄。 立即学习 “ C++免费学习笔记(深入) ”; C知道 CSDN推出的一款AI技术问答工具 下载
dwCreationDisposition
必须是
OPEN_EXISTING
(只打开已有)或
CREATE_ALWAYS
(覆盖重开),不能用
OPEN_ALWAYS
—— 后者在文件存在时仍会尝试共享打开,破坏独占语义
dwFlagsAndAttributes
中若含
FILE_ATTRIBUTE_HIDDEN
或
FILE_ATTRIBUTE_SYSTEM
,某些杀软或UAC策略会静默拒绝,建议仅用
FILE_ATTRIBUTE_NORMAL
hTemplateFile
必须传
NULL
,传任意值都会导致
INVALID_HANDLE_VALUE
且
GetLastError
返回
ERROR_INVALID_PARAMETER
示例片段:
HANDLE h = CreateFile( L"config.dat", GENERIC_READ | GENERIC_WRITE, 0, // ← 关键:禁止共享 NULL, OPEN_EXISTING, // ← 关键:不创建新文件,也不允许共享打开已有文件 FILE_ATTRIBUTE_NORMAL, NULL ); if (h == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); // 查具体原因 }
关闭句柄后文件真的“释放”了吗? 是的,但有个隐蔽前提:你得真正关掉了所有副本句柄。Windows 的句柄是引用计数的,只要还有一个线程持有该句柄(哪怕是复制过的),文件就仍处于被独占状态。 用
CloseHandle
关闭后,立即用另一个进程尝试
CreateFile(..., 0, ...)
测试是否释放成功 调试时可用
Process Explorer
搜索文件名,确认没有残留句柄(包括你自己的其他线程) 避免在异常路径中遗漏
CloseHandle
,RAII 封装(如
std::unique_ptr
配自定义 deleter)比裸调用更安全 真正的难点不在打开,而在确保整个生命周期里没有句柄泄漏、没有竞态窗口、也没有外部程序(比如编辑器、备份工具)偷偷打开它。

相关文章