我有以下每两个执行一次的代码 一整天的分钟数:
int sucessfully_deleted = DeleteFile(dest_filename);
if (!sucessfully_deleted)
{
// this never happens
}
rename(source_filename,dest_filename);
每隔几个小时,rename()将失败,并出现errno = 13(EACCES)。所涉及的文件全部位于DropBox目录中,我直觉Dropbox可能是原因。我认为DeleteFile()函数可能会返回一个非零的success_deleted,但实际上DropBox可能仍在忙于做一些与删除操作有关的事情,这些操作阻止了named()成功。接下来,我要做的是将rename()更改为my_rename(),这将尝试进行rename(),一旦失败,将Sleep()停留一秒钟,然后再次尝试。从那以后,果然如此完美。此外,每隔几个小时,我会收到一条诊断消息,显示首次尝试失败。在第二次尝试中从未失败。
所以您可以说问题已完全解决...但是我想了解可能会发生什么,以便将来更好地保护自己免受任何相关的DropBox问题...
真的,我想拥有一个新的super_delete()函数,该函数要等到正确删除并在各个方面完成后才返回。
答案 0 :(得分:3)
请求删除文件实际上从未只是删除文件。并用特殊标志(FCB_STATE_DELETE_ON_CLOSE
)将其标记为 FCB (文件控制块)。仅当最后一个文件句柄关闭时,才真正删除。
DeleteFile
函数将文件标记为关闭时要删除。因此, 直到文件的最后一个句柄是 关闭。随后调用CreateFile
打开文件失败ERROR_ACCESS_DENIED
。
如果存在的部分(内存映射文件)在文件上打开-甚至无法将文件标记为删除。 api调用失败,STATUS_CANNOT_DELETE
。因此通常不可能总是删除文件。
如果存在从Windows 10 rs1开始的另一个文件打开句柄(但不是section!),则存在删除的新功能-FileDispositionInformationEx
和FILE_DISPOSITION_POSIX_SEMANTICS
。在这种情况下:
通常,直到所有 文件的打开句柄已关闭,并且链接计数 文件为零。将文件标记为删除时 FILE_DISPOSITION_POSIX_SEMANTICS ,当POSIX删除句柄关闭后,链接就会从可见的命名空间中删除, 但是文件的数据流仍然可以被其他现有用户访问 直到最后一个手柄已关闭。
ULONG DeletePosix(PCWSTR lpFileName)
{
HANDLE hFile = CreateFileW(lpFileName, DELETE, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OPEN_REPARSE_POINT, 0);
if (hFile == INVALID_HANDLE_VALUE)
{
return GetLastError();
}
static FILE_DISPOSITION_INFO_EX fdi = { FILE_DISPOSITION_DELETE| FILE_DISPOSITION_POSIX_SEMANTICS };
ULONG dwError = SetFileInformationByHandle(hFile, FileDispositionInfoEx, &fdi, sizeof(fdi))
? NOERROR : GetLastError();
// win10 rs1: file removed from parent folder here
CloseHandle(hFile);
return dwError;
}
答案 1 :(得分:1)
更新
对不起,我第一次没有正确回答问题。我以为DeleteFile返回错误13。
现在,我了解到DeleteFile成功,但之后重命名立即失败。 它可能只是文件系统的同步问题。调用DeleteFile之后,当操作系统将更改提交到文件系统时,该文件将被删除。这可能不会立即生效。 如果需要对同一路径执行多项操作,则应查看事务https://docs.microsoft.com/it-it/windows/desktop/api/winbase/nf-winbase-deletefiletransacteda。
-旧答案-
是正确的。如果另一个应用程序处理该文件,则DeleteFile将失败。 引用MSDN文档https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-deletefile:
The DeleteFile function fails if an application attempts to delete a file that has other handles open for normal I/O or as a memory-mapped file (FILE_SHARE_DELETE must have been specified when other handles were opened).
这适用于保管箱,防病毒软件,或者通常适用于可能打开这些文件的任何其他应用程序。 Dropbox随时可以打开文件以计算其哈希值(以查找更改)。防病毒软件也是如此。