C++ DropBox是否会干扰DeleteFile()/rename()

C++ DropBox是否会干扰DeleteFile()/rename(),c++,c,visual-studio,windows-10,dropbox,C++,C,Visual Studio,Windows 10,Dropbox,我有下面的代码,每两年执行一次 全天15分钟: int sucessfully_deleted = DeleteFile(dest_filename); if (!sucessfully_deleted) { // this never happens } rename(source_filename,dest_filename); 每隔几个小时,rename()就会失败一次,错误号为13(EACCES)。涉及的文件都放在DropBox目录上,我有预感DropBox可能是原因。我认

我有下面的代码,每两年执行一次 全天15分钟:

int sucessfully_deleted = DeleteFile(dest_filename);

if (!sucessfully_deleted)
{
    // this never happens
}

rename(source_filename,dest_filename);
每隔几个小时,rename()就会失败一次,错误号为13(EACCES)。涉及的文件都放在DropBox目录上,我有预感DropBox可能是原因。我认为DeleteFile()函数可能返回一个成功删除的非零值,但实际上DropBox可能仍在忙于执行一些与删除相关的操作,这些操作阻止了rename()的成功。接下来我做的是将rename()改为我的_rename(),这将尝试重命名(),一旦失败,将Sleep()保持一秒钟,然后再试一次。果不其然,从那以后,这一切都很完美。此外,每隔几个小时我就会收到一条诊断消息,显示首次尝试失败。第二次尝试从未失败过

所以你可以说问题已经完全解决了。。。但我想了解可能发生的情况,以便更好地保护自己,防止将来出现任何相关的DropBox问题


我真的希望有一个新的super_delete()函数,它在文件被正确删除并在各个方面完成之前不会返回。

更新

对不起,我第一次没答对问题。我认为DeleteFile返回了错误13

现在我知道DeleteFile成功了,但重命名之后立即失败。 这可能只是与文件系统的同步问题。调用DeleteFile后,当操作系统将更改提交到文件系统时,该文件将被删除。这可能不会马上发生。 如果需要对同一路径执行多个操作,那么应该查看事务

--旧答案--

这是正确的。如果另一个应用程序处理该文件,DeleteFile将失败。 引用MSDN文档:

DeleteFile函数在应用程序试图删除一个文件时失败,该文件的其他句柄为正常I/O打开,或者作为内存映射文件(必须在打开其他句柄时指定file\u SHARE\u delete)。

这适用于dropbox、防病毒软件,或者一般来说,任何其他可能打开这些文件的应用程序。
Dropbox可以随时打开文件以计算其哈希值(查找更改)。杀毒软件也是如此

在windows下请求删除文件时,绝对不要只删除文件。它用特殊标志(
FCB\u STATE\u DELETE\u ON\u CLOSE
)将其标记为FCB(文件控制块)。真正的删除将仅在最后一个文件句柄关闭时进行

该函数在关闭时标记要删除的文件。所以,, 直到文件的最后一个句柄被删除,文件才会被删除 关闭后续调用
CreateFile
打开文件失败,原因是
错误\u访问被拒绝

此外,如果存在部分(内存映射文件)在文件上打开-文件甚至不能标记为删除。api调用失败,状态为“无法删除”。所以一般不可能总是删除文件

如果存在另一个打开的文件句柄(但不是节!),请从windows 10 rs1 exist开始为delete-with创建新函数。在这种情况下:

通常,标记为删除的文件在所有 文件的打开句柄已关闭,并且 文件为零。使用将文件标记为删除时 FILE\u DISPOSITION\u POSIX\u SEMANTICS,一旦POSIX删除句柄关闭,链接就会从可见名称空间中删除, 但该文件的数据流仍然可以被其他现有用户访问 直到最后一个句柄关闭为止


您是否知道13是
EACCES
又称“权限被拒绝”?它是在什么操作系统上的?@MichaelVeksler:从“
DeleteFile()
”我推断它是Windows。编辑问题以回答评论。在我看来,这似乎是
DeleteFile()
函数没有“自动”删除,但不知怎的,删除请求排队了。因此,您的重试方法是有意义的。另一方面,由于我们不知道“排队”需要多长时间……OP提到,
DeleteFile()
从不返回失败。从您链接的文档中,我觉得这更有趣:“DeleteFile函数在关闭时标记要删除的文件。因此,在关闭文件的最后一个句柄之前,不会删除文件。“对不起,我的错误。我相应地更新了答案。是的,DeleteFile不会立即删除文件,这就是为什么后续重命名调用可能失败的原因。”DeleteFile不会立即删除文件“我觉得这个功能完全被破坏了。我同意这个名字有误导性。它应该像MarkforDelete一样。前面已经讨论过了,所以:在这个答案中有很多我不理解的东西-您是否声称此函数将删除文件,并且在文件完全删除之前不会返回(就像我在OP中建议的super_delete())@Mick-
DeletePosix
从可见名称空间中删除。因此,您可以使用此名称创建/重命名新文件。如果此文件没有其他打开的句柄-它将被删除,否则仅当最后一个打开的句柄关闭时。如果文件中存在,则调用失败。但在这种情况下,一切都失败了。如果你的DeleteFile没有失败——这意味着你的混凝土中没有关于文件的部分case@Mick-因此,如果文件上存在其他打开的句柄-它将不会被完全删除-这是不可能的,直到句柄未关闭。但它的名称将从文件夹中删除(取消链接)。你可以重命名为这个name@Mick总之,这是一个通用概念,即使C++视图对象(文件)在存在引用(句柄)之前也不能删除。代码>删除文件不能只删除文件。它只能在最后一个对象引用关闭/释放时将其标记为删除。如果存在外部引用-它可以无限长地存在-如果等待-
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;
}