植物大战僵尸杂交版现已更新到v2.0.88,闪退问题还是偶有发生,参考网上现有的方案,简单实现了一个。
原理就是监控存档目录的文件变化,一旦有新的存档,则将其备份。如发生闪退,则还原备份即可。
原目录:C:/ProgramData/PopCap Games/PlantsVsZombies/pvzHE/yourdata
备份目录:C:/ProgramData/PopCap Games/PlantsVsZombies/pvzHE/yourdata_Backup
源代码
cpp
#include <windows.h>
#include <iostream>
#include <filesystem>
#include <string>
#include <vector>
namespace fs = std::filesystem;
void copy_directory(const fs::path &source, const fs::path &destination)
{
try
{
if (!fs::exists(destination))
{
fs::create_directories(destination);
}
for (const auto &entry : fs::recursive_directory_iterator(source))
{
const auto &path = entry.path();
auto relativePathStr = path.lexically_relative(source).string();
fs::copy(path, destination / relativePathStr, fs::copy_options::overwrite_existing);
}
}
catch (const std::exception &e)
{
std::cerr << "Error: " << e.what() << std::endl;
}
}
void monitor_directory(const std::wstring &path, const std::wstring &backup_path)
{
HANDLE hDir = CreateFileW(
path.c_str(),
FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if (hDir == INVALID_HANDLE_VALUE)
{
std::cerr << "CreateFile failed with " << GetLastError() << std::endl;
return;
}
char buffer[1024];
DWORD bytesReturned;
FILE_NOTIFY_INFORMATION *pNotify;
std::vector<char> filenameBuffer(MAX_PATH);
while (true)
{
if (ReadDirectoryChangesW(
hDir,
buffer,
sizeof(buffer),
FALSE,
FILE_NOTIFY_CHANGE_FILE_NAME,
&bytesReturned,
NULL,
NULL))
{
pNotify = (FILE_NOTIFY_INFORMATION *)buffer;
do
{
std::wstring filename(pNotify->FileName, pNotify->FileNameLength / sizeof(WCHAR));
if (pNotify->Action == FILE_ACTION_ADDED)
{
std::wcout << L"New file created: " << filename << std::endl;
copy_directory(path, backup_path);
}
pNotify = (FILE_NOTIFY_INFORMATION *)((char *)pNotify + pNotify->NextEntryOffset);
} while (pNotify->NextEntryOffset != 0);
}
else
{
std::cerr << "ReadDirectoryChangesW failed with " << GetLastError() << std::endl;
break;
}
}
CloseHandle(hDir);
}
int main()
{
std::wstring directory_to_monitor = L"C:/ProgramData/PopCap Games/PlantsVsZombies/pvzHE/yourdata";
std::wstring backup_directory = L"C:/ProgramData/PopCap Games/PlantsVsZombies/pvzHE/yourdata_Backup";
std::cout << "开始运行" << std::endl;
monitor_directory(directory_to_monitor, backup_directory);
return EXIT_SUCCESS;
}
注意
需要使用MSVC(VS 2022)以GBK编码保存代码 编译,如需用MinGW编译,则要手动修改部分代码。