C++ 如何使我的程序不会删除正在使用的文件?

C++ How do I make it so my program wouldn't delete files that are in use?

基本上,我列出了临时目录中的所有文件,然后删除它们。显然,一些文件正在使用中,而程序本身正在使用它正在删除的文件。我尝试摆弄 SHFileOperation 但没有成功。 (说实话我不知道如何使用它)。如何让它在删除文件之前检查该文件是否正在被另一个程序使用?谢谢!

这是给我的错误:fs::remove_all(entry.path());

代码:

#include <iostream>
#include <Windows.h>
#include <filesystem>
#include <lmcons.h>
#include <fileapi.h>
#include "cColors.h"
using namespace std;

namespace fs = filesystem;
char type;

int main()
{
    SetConsoleTextAttribute(h, 15);

    while (true)
    {
        cout << "[~] Are you sure you want to run Windows Cleaner? [Y/N]";
        cin >> type;

        if (type == 'n')
        {
            break;
            exit(0);
        }
        else if (type == 'y')
        {
            cout << "[#] Cleaning temp directory\n";

            for (const auto& entry : fs::directory_iterator(fs::temp_directory_path()))
            {
                cout << "[#] Deleting " << entry.path();
                fs::remove_all(entry.path()); //This is giving me the error
            }       
        }
        else
        {
            break;
            exit(0);
        }
    }
}

捕获异常忽略错误并继续。或者使用第二种形式并传递一个 error_code 参数。比你没有例外,你可以检查它失败的原因。

如果文件正在使用中,您会收到错误消息。所以你不能删除它。如果你没有权限,你也不能删除它。

首先检查使用情况是竞争条件。检查后,文件可能会关闭,您可以安全地删除它。首先检查和删除它或尝试删除它但失败没有区别。

这是我想出的。使用 CreateFile 的递归删除函数。我的原评论

Maybe you could use CreateFile with desired access 0 and share mode OPEN_EXISTING. Then you have to check the failing reason. If it doesn't fail; close and delete.

并非 100% 正确。 dwDesiredAccess 应该是 0dwShareMode 应该是 FILE_SHARE_DELETEdwCreationDisposition 应该OPEN_EXISTING 并且 dwFlagsAndAttributes 应该是 FILE_FLAG_DELETE_ON_CLOSE。如果收到有效句柄,文件上的最后一个 CloseHandle 将导致删除(参见 here)。

这是一个例子:

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <tchar.h>
#include <iostream>
#include <filesystem>

#ifdef _UNICODE
auto& cout = std::wcout;
#else
using std::cout;
#endif // _UNICODE
using std::endl;
namespace fs=std::filesystem;

void deleteRecursive(const fs::path& path);
void tryDeleteFile(const fs::path& path);

int main(int argc, char* argv[])
{
    TCHAR tempDir[255];
    GetEnvironmentVariable(_T("TEMP"), tempDir, 255);
    deleteRecursive(fs::path(tempDir));
    return 0;
}

void deleteRecursive(const fs::path& path)
{
    fs::directory_iterator dirs(path);
    for (const auto& entry : dirs)
    {
        const auto& path = entry.path();
        if (entry.is_directory())
        {
            deleteRecursive(path);
            if (fs::is_empty(path))
            {
                if (!RemoveDirectory(path.c_str()))
                {
                    cout << _T("Can't delete dir: ") << path << endl;
                }
            }
        }
        else
        {
            tryDeleteFile(path);
        }
    }
}

void tryDeleteFile(const fs::path& path)
{
    const auto file = path.c_str();
    HANDLE fileHandle = CreateFile(
        file,                      // lpFileName,
        0,                         // dwDesiredAccess,
        FILE_SHARE_DELETE,         // dwShareMode,
        NULL,                      // lpSecurityAttributes,
        OPEN_EXISTING,             // dwCreationDisposition,
        FILE_FLAG_DELETE_ON_CLOSE, // dwFlagsAndAttributes,
        NULL                       // hTemplateFile
    );
    if (fileHandle == INVALID_HANDLE_VALUE)
    {
        DWORD lastErr = GetLastError();
        if (lastErr != ERROR_FILE_NOT_FOUND) // gone in the mean time
        {
            cout << _T("Can't delete file: ") << file << endl;
        }
    }
    else
    {
        CloseHandle(fileHandle);
    }
}

tryDeleteFile 包含关键部分。