11

最初に非常に長い一時ファイルを作成し、それを閉じ、読み取り用に開き、読み取り、再度閉じ、DeleteFile().

通常はスムーズに進みDeleteFile(ますが、 ) が失敗してGetLastError()ERROR_ACCESS_DENIED を返すことがあります。ファイルは確かに読み取り専用ではありません。どのサイズのファイルでも発生しますが、ファイル サイズが大きくなるにつれて確率が高くなります。

ファイルをロックしている可能性のあるアイデアはありますか? WinInternals ツールを試してみましたが、疑わしいものは何も見つかりませんでした。

4

7 に答える 7

11

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.                                          
*/
于 2009-11-18T04:34:36.727 に答える
9

勝手な推測ですが、ウイルス対策ソフトウェアをインストールしていますか? リアルタイム保護機能を無効にしてみましたか?

于 2009-11-18T02:32:15.230 に答える
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;
}
于 2009-11-18T06:55:08.693 に答える
4

DeleteFile() を呼び出す前に MessageBox() 呼び出しを追加します。それが表示されたら、sysinternals ツールの Process Explorer を実行します。ファイルへの開いているハンドルを検索します。おそらく、ファイルへのすべてのハンドルを閉じていません...

于 2009-11-18T02:24:02.323 に答える
1

変更がまだキャッシュされていて、まだ保存されていない可能性がありますか?

これは、ファイル ハンドルにWaitForSingleObjectを追加することで確認できます。

于 2009-11-18T02:22:16.670 に答える
-1
#include <iostream>
#include <windows.h>

int main(int argc, const char * argv[])
{
    // Get a pointer to the file name/path
    const char * pFileToDelete = "h:\\myfile.txt";
    bool RemoveDirectory("h:\\myfile.txt");

    // try deleting it using DeleteFile
    if(DeleteFile(pFileToDelete ))
    {
        // succeeded
        std::cout << "Deleted file"  << std::endl;
    }
    else
    {
        // failed
        std::cout << "Failed to delete the file" << std::endl;
    }
    std::cin.get();
    return 0;
}  
于 2012-08-27T01:17:18.930 に答える