C++ C++/Win32:如何等待挂起的删除完成
已解决:C++ C++/Win32:如何等待挂起的删除完成,c++,winapi,file-io,ntfs,C++,Winapi,File Io,Ntfs,已解决: 可行的解决方案: 对实际发生的情况的解释: 解释OpenFile为什么不通过“删除挂起”: 问题: 我们的软件在很大程度上是专用脚本语言的解释器引擎。该脚本语言能够创建文件、处理文件,然后删除文件。这些都是单独的操作,在这些操作之间没有文件句柄保持打开状态 (即,在文件创建过程中,创建一个句柄,用于写入,然后关闭。在文件处理部分,一个单独的文件句柄打开文件,从中读取,然后在EOF关闭。最后,delete使用::DeleteFile,它只使用文件名,根本不使用文件句柄) 最近,我们意
- 可行的解决方案:
- 对实际发生的情况的解释:
- 解释OpenFile为什么不通过“删除挂起”:
while (true) {
HANDLE hFile = CreateFileA(pszFilename, FILE_ALL_ACCESS, FILE_SHARE_READ,
NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return OpenFailed;
const DWORD dwWrite = strlen(pszFilename);
DWORD dwWritten;
if (!WriteFile(hFile, pszFilename, dwWrite, &dwWritten, NULL) || dwWritten != dwWrite)
return WriteFailed;
if (!CloseHandle(hFile))
return CloseFailed;
if (!DeleteFileA(pszFilename))
return DeleteFailed;
}
如您所见,这是直接指向Win32 API的,非常简单。我创建一个文件,写入它,关闭手柄,删除它,冲洗,重复
但是在调用CreateFile()的过程中,我会遇到一个访问被拒绝(5)错误。查看sysinternal的ProcessMonitor,我可以看到潜在的问题是,当我再次尝试创建文件时,文件上有一个挂起的删除
问题:
- 是否有办法等待删除完成
- 有没有办法检测到文件正在等待删除
bool DeleteFileNowA(const char * pszFilename)
{
// Determine the path in which to store the temp filename
char szPath[MAX_PATH];
strcpy(szPath, pszFilename);
PathRemoveFileSpecA(szPath);
// Generate a guaranteed to be unique temporary filename to house the pending delete
char szTempName[MAX_PATH];
if (!GetTempFileNameA(szPath, ".xX", 0, szTempName))
return false;
// Move the real file to the dummy filename
if (!MoveFileExA(pszFilename, szTempName, MOVEFILE_REPLACE_EXISTING))
return false;
// Queue the deletion (the OS will delete it when all handles (ours or other processes) close)
if (!DeleteFileA(szTempName))
return false;
return true;
}
首先重命名要删除的文件,然后将其删除 使用
GetTempFileName()
获取唯一名称,然后使用MoveFile()
重命名文件。然后删除重命名的文件。如果实际的删除确实是异步的,并且可能与同一文件的创建冲突(正如您的测试所表明的),那么这应该可以解决问题
当然,如果您的分析是正确的,并且文件操作在某种程度上是异步的,这可能会导致您在重命名之前尝试删除文件的问题。但是你可以一直尝试在后台线程中删除
如果Hans是对的(我倾向于相信他的分析),那么移动可能没有真正的帮助,因为您可能无法实际重命名由另一个进程打开的文件。(但你可能会,我不知道这一点。)如果真是这样,我唯一能想到的办法就是“继续努力”。您必须等待几毫秒,然后重试。保留一个超时时间以在没有帮助时放弃。如果CreateFile返回无效的\u HANDLE\u值,那么您应该确定在特定情况下(挂起的删除)GetLastError返回的内容,并仅基于该错误代码循环回CreateFile
文件标志\u DELETE\u ON\u CLOSE标志可能会为您购买一些东西。Windows中还有其他进程需要该文件的一部分。搜索索引器显然是一个候选对象。或者是病毒扫描器。他们将打开文件进行完全共享,包括文件共享和删除,这样其他进程就不会受到他们打开文件的严重影响 这通常效果很好,除非您以高速率创建/写入/删除。删除将成功,但在关闭文件的最后一个句柄之前,该文件无法从文件系统中消失。例如,由搜索索引器控制的句柄。任何试图打开挂起的删除文件的程序都将被错误5击打
否则,这是多任务操作系统上的一个常见问题,您无法知道其他进程可能会将文件弄乱。您的使用模式似乎不寻常,请先回顾一下。一种解决方法是捕获错误,休眠并重试。或者使用SHFileOperation()将文件移动到回收站。我认为这是由于文件系统设计不当造成的。我在使用通信端口时也遇到过同样的问题,打开/关闭它们 不幸的是,我认为最简单的解决办法是
10:39:10.1738151 AM jam.exe 5032 CreateFile C:\Users\Dad\AppData\Local\Temp\jam5032t1.bat SUCCESS Desired Access: Read Attributes, Delete, Disposition: Open, Options: Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
10:39:10.1738581 AM jam.exe 5032 QueryAttributeTagFile C:\Users\Dad\AppData\Local\Temp\jam5032t1.bat SUCCESS Attributes: ANCI, ReparseTag: 0x0
10:39:10.1738830 AM jam.exe 5032 SetDispositionInformationFile C:\Users\Dad\AppData\Local\Temp\jam5032t1.bat SUCCESS Delete: True
10:39:10.1739216 AM jam.exe 5032 CloseFile C:\Users\Dad\AppData\Local\Temp\jam5032t1.bat SUCCESS
10:39:10.1739438 AM jam.exe 5032 IRP_MJ_CLOSE C:\Users\Dad\AppData\Local\Temp\jam5032t1.bat SUCCESS
10:39:10.1744837 AM jam.exe 5032 CreateFile C:\Users\Dad\AppData\Local\Temp\jam5032t1.bat DELETE PENDING Desired Access: Generic Write, Read Attributes, Disposition: OverwriteIf, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: Read, Write, AllocationSize: 0
10:39:10.1788811 AM jam.exe 5032 CreateFile C:\Users\Dad\AppData\Local\Temp\jam5032t1.bat DELETE PENDING Desired Access: Generic Write, Read Attributes, Disposition: OverwriteIf, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: Read, Write, AllocationSize: 0
10:39:10.1838276 AM jam.exe 5032 CreateFile C:\Users\Dad\AppData\Local\Temp\jam5032t1.bat DELETE PENDING Desired Access: Generic Write, Read Attributes, Disposition: OverwriteIf, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: Read, Write, AllocationSize: 0
10:39:10.1888407 AM jam.exe 5032 CreateFile C:\Users\Dad\AppData\Local\Temp\jam5032t1.bat DELETE PENDING Desired Access: Generic Write, Read Attributes, Disposition: OverwriteIf, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: Read, Write, AllocationSize: 0
10:39:10.1936323 AM System 4 FASTIO_ACQUIRE_FOR_SECTION_SYNCHRONIZATION C:\Users\Dad\AppData\Local\Temp\jam5032t1.bat SUCCESS SyncType: SyncTypeOther
10:39:10.1936531 AM System 4 FASTIO_RELEASE_FOR_SECTION_SYNCHRONIZATION C:\Users\Dad\AppData\Local\Temp\jam5032t1.bat SUCCESS
10:39:10.1936647 AM System 4 IRP_MJ_CLOSE C:\Users\Dad\AppData\Local\Temp\jam5032t1.bat SUCCESS
10:39:10.1939064 AM jam.exe 5032 CreateFile C:\Users\Dad\AppData\Local\Temp\jam5032t1.bat DELETE PENDING Desired Access: Generic Write, Read Attributes, Disposition: OverwriteIf, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: Read, Write, AllocationSize: 0
10:39:10.1945733 AM cmdagent.exe 1188 CloseFile C:\Users\Dad\AppData\Local\Temp\jam5032t1.bat SUCCESS
10:39:10.1946532 AM cmdagent.exe 1188 IRP_MJ_CLOSE C:\Users\Dad\AppData\Local\Temp\jam5032t1.bat SUCCESS
10:39:10.1947020 AM cmdagent.exe 1188 IRP_MJ_CLOSE C:\Users\Dad\AppData\Local\Temp\jam5032t1.bat SUCCESS
10:39:10.1948945 AM cfp.exe 1832 QueryOpen C:\Users\Dad\AppData\Local\Temp\jam5032t1.bat FAST IO DISALLOWED
10:39:10.1949781 AM cfp.exe 1832 CreateFile C:\Users\Dad\AppData\Local\Temp\jam5032t1.bat NAME NOT FOUND Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
10:39:10.1989720 AM jam.exe 5032 CreateFile C:\Users\Dad\AppData\Local\Temp\jam5032t1.bat SUCCESS Desired Access: Generic Write, Read Attributes, Disposition: OverwriteIf, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: Read, Write, AllocationSize: 0, OpenResult: Created