【问题标题】:C++ How do I make it so my program wouldn't delete files that are in use?C++ 我怎样才能让我的程序不会删除正在使用的文件?
【发布时间】:2019-11-27 21:57:01
【问题描述】:

所以基本上,我列出了我的临时目录中的所有文件,然后删除它们。显然,有些文件正在使用中,而程序本身正在使用它正在删除的文件。我尝试摆弄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);
        }
    }
}

【问题讨论】:

  • 如果文件已经打开,您通常无法删除它们。
  • 也许您可以将CreateFile所需访问权限 0共享模式 OPEN_EXISTING 一起使用。然后你必须检查失败的原因。如果没有失败;关闭并删除。
  • How do I find out which process has a file open? 但实际上,这只是引入了另一场 TOCTTOU 比赛。为什么不尝试删除它?系统已经完成了您尝试复制的操作。
  • @JonathanPotter 你可以删除一个正在使用的文件(权限允许),它实际上不会被删除,直到它的所有打开的句柄都被关闭。

标签: c++ winapi delete-file


【解决方案1】:

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

如果文件正在使用中,则会出现错误。所以你不能删除它。如果你没有权利,你也不能删除它。

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

【讨论】:

  • 一个正在使用的文件并不意味着你不能在它上面调用DeleteFile。如果文件的所有打开句柄都通过了FILE_SHARE_DELETE 共享模式,则尝试删除文件不会导致ERROR_SHARING_VIOLATION 错误。
  • @IInspectable 如果有,他们可能不在乎是否有人删除它。
  • @cal:我只是在评论声明的不准确之处。
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 2020-03-24
    • 2020-01-19
    • 2016-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-07
    • 2012-01-16
    相关资源
    最近更新 更多