C ++如何做到这一点,以便我的程序不会删除正在使用的文件?

时间:2019-11-27 21:57:01

标签: c++ winapi delete-file

因此,基本上,我将列出temp目录中的所有文件,然后将其删除。显然,某些文件正在使用中,程序本身正在使用要删除的文件。我尝试摆弄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);
        }
    }
}

2 个答案:

答案 0 :(得分:1)

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

如果文件正在使用中,则会出现错误。因此,您无法删除它。如果您没有权限,也无法删除它。

首先检查使用情况是一种竞争状况。检查之后,文件可能会关闭,您也许可以安全地删除它。先检查然后删除或尝试删除它并失败都没有区别。

答案 1 :(得分:0)

这就是我想出的。使用CreateFile的递归删除功能。我的原始评论

  

也许您可以将CreateFile与所需的访问权限0一起使用,并将共享模式设为OPEN_EXISTING。然后,您必须检查失败的原因。如果没有失败;关闭并删除。

不是100%正确。 dwDesiredAccess 应该为0 dwShareMode 应该为FILE_SHARE_DELETE dwCreationDisposition 应该为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包含关键部分。