DeleteFile在最近关闭的文件上失败

Dmi*_*nik 8 c++ winapi file delete-file

我有一个单线程程序(C++,Win32,NTFS),它首先创建一个相当长的临时文件,关闭它,打开以进行读取,读取,再次关闭并尝试使用删除DeleteFile().

通常它顺利进行,但有时会DeleteFile(失败,并GetLastError()返回ERROR_ACCESS_DENIED.文件不是只读的.它发生在任何大小的文件上,但概率随文件大小而增加.

什么可能锁定文件的想法?我尝试使用WinInternals工具进行检查,发现没有任何可疑之处.

Sna*_*zer 10

Windows因此问题而臭名昭着.SQLite通过每100毫秒重复删除操作直到最大数量来处理问题.

我相信如果您确定没有打开的句柄,那么在您的实现中执行此操作将会让您在防病毒软件打开文件时遇到麻烦.

供参考,来自SQLite来源的评论:

/*                                                                     
** Delete the named file.                                              
**                                                                     
** Note that windows does not allow a file to be deleted if some other
** process has it open.  Sometimes a virus scanner or indexing program
** will open a journal file shortly after it is created in order to do
** whatever it does.  While this other process is holding the          
** file open, we will be unable to delete it.  To work around this     
** problem, we delay 100 milliseconds and try to delete again.  Up     
** to MX_DELETION_ATTEMPTs deletion attempts are run before giving     
** up and returning an error.                                          
*/
Run Code Online (Sandbox Code Playgroud)


Ori*_*ach 9

只是猜测 - 您是否安装了任何防病毒软件?您是否尝试过禁用其中的任何实时保护功能?

  • 这个答案完全应该是正确的. (3认同)

Nat*_*ell 5

我相信Windows Internals中对此进行了介绍。简而言之,即使您在文件句柄上调用了 CloseHandle,内核可能仍然有未完成的引用,需要几毫秒才能关闭。

完成后删除文件的更可靠方法是在打开最后一个句柄时使用 FILE_FLAG_DELETE_ON_CLOSE 标志。如果您可以避免在读/写之间关闭文件,那么效果会更好。

#include <windows.h>
#include <stdio.h>

int wmain(int argc, wchar_t** argv)
{
    LPCWSTR fileName = L"c:\\temp\\test1234.bin";

    HANDLE h1 = CreateFileW(
        fileName,
        GENERIC_WRITE,
        // make sure the next call to CreateFile can succeed if this handle hasn't been closed yet
        FILE_SHARE_READ | FILE_SHARE_DELETE,
        NULL,
        CREATE_ALWAYS,
        FILE_FLAG_SEQUENTIAL_SCAN | FILE_ATTRIBUTE_TEMPORARY,
        NULL);
    if (h1 == INVALID_HANDLE_VALUE)
    {
        fprintf(stderr, "h1 failed: 0x%x\n", GetLastError());
        return GetLastError();
    }

    HANDLE h2 = CreateFileW(
        fileName,
        GENERIC_READ,
        // FILE_SHARE_WRITE is required in case h1 with GENERIC_WRITE access is still open
        FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
        NULL,
        OPEN_EXISTING,
        // tell the OS to delete the file as soon as it is closed, no DeleteFile call needed
        FILE_FLAG_DELETE_ON_CLOSE | FILE_FLAG_SEQUENTIAL_SCAN | FILE_ATTRIBUTE_TEMPORARY,
        NULL);
    if (h2 == INVALID_HANDLE_VALUE)
    {
        fprintf(stderr, "h2 failed: 0x%x\n", GetLastError());
        return GetLastError();
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)


Ami*_*shk 1

也许更改仍然被缓存并且尚未保存?

您可以通过在文件句柄上添加WaitForSingleObject来检查这一点以确定。

  • 写缓存对应用程序是透明的。它不应导致行为改变。 (4认同)