SHFileOperation执行FO_DELETE时,被占用文件未触发预期报错的问题
关于SHFileOperation删除锁定文件时的错误触发场景
为什么你的测试场景未触发错误
你用SHFileOperation配合FOF_ALLOWUNDO删除被记事本/Notepad++打开的文件时操作成功,核心原因是这些程序的文件共享模式:
- 记事本默认以
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE模式打开文件,允许其他进程执行删除操作。删除后,记事本持有的是已被删除文件的句柄,保存时会创建新文件覆盖原路径(本质是生成新文件)。 - Notepad++的文件打开模式同样允许删除操作,只是后续会主动检测文件状态并向用户提示。
SHFileOperation能完成删除,是因为文件并未被排他性锁定。
触发“无法删除文件,它正被另一个进程锁定”错误的场景
只有当目标文件被其他进程以禁止删除的共享模式打开,或进程持有文件的排他锁时,才会触发该错误,具体场景包括:
- 进程以无删除共享的模式打开文件:比如调用
CreateFile时仅指定FILE_SHARE_READ | FILE_SHARE_WRITE(缺少FILE_SHARE_DELETE),此时其他进程无法删除该文件。数据库客户端、视频编辑工具等专业软件常使用这种模式,防止文件被意外删除。 - 进程持有文件的排他锁:文件复制工具在复制过程中、杀毒软件扫描文件时,会对文件加排他锁,此时任何修改、删除操作都会被阻止。
- 文件被系统服务或内核进程锁定:系统索引服务、Windows Defender实时保护读取文件时,或文件作为系统资源被内核进程占用(如页面文件、日志文件),删除操作会直接失败。
- 文件是正在运行的可执行文件:若要删除的是正在运行的
.exe、.dll等程序文件,系统会阻止删除——因为进程正在占用这些文件的内存映射,无法释放句柄。
额外说明
SHFileOperation是高层Shell操作,其错误反馈依赖底层API的返回结果。如果底层DeleteFile或MoveFile(删除到回收站本质是移动操作)能成功执行,它就会返回0;只有当底层操作因锁定失败时,才会返回非零错误码并触发系统提示。
你的测试代码
// std::wstring filePath contains the full path SHFILEOPSTRUCT fileOp; ZeroMemory(&fileOp, sizeof(fileOp)); fileOp.hwnd = NULL; // no dialog for any status notification fileOp.wFunc = FO_DELETE; // pFrom must be doubly-null-terminated WCHAR doublyNullTerminatedFrom[MAX_PATH] = { 0 }; StrCpy(doublyNullTerminatedFrom, filePath.c_str()); CopyMemory(doublyNullTerminatedFrom + lstrlen(doublyNullTerminatedFrom), "\0\0", 2); // Append double null fileOp.pFrom = doublyNullTerminatedFrom; fileOp.pTo = NULL; fileOp.fFlags = FOF_ALLOWUNDO; // To Recycle Bin with Undo. Also, full path is required to delete to Recycle Bin (present here) int result = SHFileOperation(&fileOp); // In case of failure returns a non-zero result if (result != 0) { // ... Success on file open in another application, doesn't come here }
内容的提问来源于stack exchange,提问作者gene b.
相关产品推荐
相关产品推荐

