DeleteFile перестал работать на недавно закрытом файле

Я не использую VIM, но значение по умолчанию Powershell произвело, Unicode. Блокнот может считать unicode, Вы могли использовать его, чтобы видеть, получаете ли Вы вывод, Вы ожидаете.

8
задан Brian Tompsett - 汤莱恩 4 July 2015 в 13:17
поделиться

5 ответов

Просто дикая догадка - у вас установлено какое-нибудь антивирусное программное обеспечение? Вы пытались отключить в нем какие-либо функции защиты в реальном времени?

9
ответ дан 5 December 2019 в 06:09
поделиться

Я считаю, что это описано в Внутренних компонентах Windows . Вкратце, даже если вы вызвали 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;
}
3
ответ дан 5 December 2019 в 06:09
поделиться

Добавьте вызов MessageBox () перед вызовом DeleteFile (). Когда он появится, запустите инструмент Process Explorer для sysinternals. Найдите открытый дескриптор файла. По всей видимости, вы закрыли не все дескрипторы файла ...

4
ответ дан 5 December 2019 в 06:09
поделиться

Может быть, изменения все еще кэшированы и еще не сохранены?

Вы можете проверить это, добавив WaitForSingleObject на дескриптор файла, чтобы быть уверенным.

1
ответ дан 5 December 2019 в 06:09
поделиться

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.                                          
*/
10
ответ дан 5 December 2019 в 06:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: