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 应该是 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
包含关键部分。
基本上,我列出了临时目录中的所有文件,然后删除它们。显然,一些文件正在使用中,而程序本身正在使用它正在删除的文件。我尝试摆弄 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 应该是 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
包含关键部分。