C++ 在Windows QDir::mkpath和QFile::重命名报告成功,尽管失败
我正在尝试将自动更新功能添加到我正在使用的应用程序中。我的解决方案在Linux上运行良好,但在Windows上我遇到了奇怪的问题 解包更新包后,我尝试使用以下功能将其移动到目标目录:C++ 在Windows QDir::mkpath和QFile::重命名报告成功,尽管失败,c++,windows,qt,C++,Windows,Qt,我正在尝试将自动更新功能添加到我正在使用的应用程序中。我的解决方案在Linux上运行良好,但在Windows上我遇到了奇怪的问题 解包更新包后,我尝试使用以下功能将其移动到目标目录: inline void recursiveMoveOrCopy(QDir source, QDir dest, bool move) { auto files = source.entryInfoList(QDir::Files); auto dirs = source.entryInfoList(
inline void recursiveMoveOrCopy(QDir source, QDir dest, bool move)
{
auto files = source.entryInfoList(QDir::Files);
auto dirs = source.entryInfoList(QDir::Dirs|QDir::NoDotAndDotDot);
// move / copy files
bool success = QDir{}.mkpath(dest.path());
if (!success){
throw std::runtime_error(qs("Could not crate directory %1")
.arg(dest.path()).toStdString());
}
qDebug()<<"created directory"<<dest.path();
dumpvar(QDir{}.exists(dest.path()));
for (auto& file: files){
QString sourcePath = file.filePath();
QString fileName = file.fileName();
QString destPath = dest.filePath(fileName);
QString backupPath = destPath + "_bck";
bool success;
bool backup = false;
if (QFile::exists(destPath))
backup = QFile::rename(destPath, backupPath);
ON_EXIT{
if (backup) {
QFile::remove(destPath);
QFile::rename(backupPath, destPath);
}
};
if (move) success = QFile::rename(sourcePath, destPath);
else success = QFile::copy(sourcePath, destPath);
qDebug()<<qs("move from %1 to %2 was %3").arg(sourcePath, destPath, success?"successful":"not sucessful");
if (success && backup){
QFile::remove(backupPath);
backup = false;
}
if (!success){
throw std::runtime_error(qs("Failed to %1 file %2 to %3")
.arg(move?"move":"copy")
.arg(sourcePath)
.arg(destPath)
.toStdString());
}
}
// recursively move/copy dirs
for (auto &dir: dirs) recursiveMoveOrCopy(dir.filePath(), dest.filePath(dir.fileName()), move);
}
"moving C:/Users/piotrek/AppData/Local/Temp/dres-update-image to C:/Program Files (x86)/DRES"
created directory "C:/Program Files (x86)/DRES"
QDir{}.exists(dest.path()) = true
"move from C:/Users/piotrek/AppData/Local/Temp/dres-update-image/plik2 to C:/Program Files (x86)/DRES/plik2 was successful"
created directory "C:/Program Files (x86)/DRES/katalog"
QDir{}.exists(dest.path()) = true
"move from C:/Users/piotrek/AppData/Local/Temp/dres-update-image/katalog/plik to C:/Program Files (x86)/DRES/katalog/plik was successful"
当我尝试安装此“更新”时,move函数会将以下内容写入调试输出:
inline void recursiveMoveOrCopy(QDir source, QDir dest, bool move)
{
auto files = source.entryInfoList(QDir::Files);
auto dirs = source.entryInfoList(QDir::Dirs|QDir::NoDotAndDotDot);
// move / copy files
bool success = QDir{}.mkpath(dest.path());
if (!success){
throw std::runtime_error(qs("Could not crate directory %1")
.arg(dest.path()).toStdString());
}
qDebug()<<"created directory"<<dest.path();
dumpvar(QDir{}.exists(dest.path()));
for (auto& file: files){
QString sourcePath = file.filePath();
QString fileName = file.fileName();
QString destPath = dest.filePath(fileName);
QString backupPath = destPath + "_bck";
bool success;
bool backup = false;
if (QFile::exists(destPath))
backup = QFile::rename(destPath, backupPath);
ON_EXIT{
if (backup) {
QFile::remove(destPath);
QFile::rename(backupPath, destPath);
}
};
if (move) success = QFile::rename(sourcePath, destPath);
else success = QFile::copy(sourcePath, destPath);
qDebug()<<qs("move from %1 to %2 was %3").arg(sourcePath, destPath, success?"successful":"not sucessful");
if (success && backup){
QFile::remove(backupPath);
backup = false;
}
if (!success){
throw std::runtime_error(qs("Failed to %1 file %2 to %3")
.arg(move?"move":"copy")
.arg(sourcePath)
.arg(destPath)
.toStdString());
}
}
// recursively move/copy dirs
for (auto &dir: dirs) recursiveMoveOrCopy(dir.filePath(), dest.filePath(dir.fileName()), move);
}
"moving C:/Users/piotrek/AppData/Local/Temp/dres-update-image to C:/Program Files (x86)/DRES"
created directory "C:/Program Files (x86)/DRES"
QDir{}.exists(dest.path()) = true
"move from C:/Users/piotrek/AppData/Local/Temp/dres-update-image/plik2 to C:/Program Files (x86)/DRES/plik2 was successful"
created directory "C:/Program Files (x86)/DRES/katalog"
QDir{}.exists(dest.path()) = true
"move from C:/Users/piotrek/AppData/Local/Temp/dres-update-image/katalog/plik to C:/Program Files (x86)/DRES/katalog/plik was successful"
如:每个操作都成功了。但是当我查看目标目录时,目录katalog
不存在(但是文件plik2
存在)
请注意,即使该目录不存在,QDir::exists也会报告它确实存在
这不是权限问题,当我测试这个时,我修改了C:/ProgramFiles(x86)/DRES
,让每个人都能访问
请告诉我我没有疯。这到底是怎么回事
编辑:由于鲁道夫建议使用进程监视器,我发现文件实际上正在写入C:\Users\piotrek\AppData\Local\VirtualStore\Program files(x86)\DRES
。这里到底发生了什么?我该如何解决这个问题?好的,我已经解决了
我必须使用以下代码禁用整个应用程序的VirtualStore虚拟化:
#ifdef Q_OS_WIN32
#include <windows.h>
QString getWinError()
{
DWORD dw = GetLastError();
LPWSTR lpMsgBuf = NULL;
FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR) &lpMsgBuf,
0, NULL );
QString str = QString::fromWCharArray(lpMsgBuf);
LocalFree(lpMsgBuf);
return str;
}
bool disableVirtualStore()
{
HANDLE token;
DWORD tokenInformation = 0;
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token)){
qWarning()<<getWinError();
return FALSE;
}
ON_EXIT{
CloseHandle(token);
};
if(!SetTokenInformation(token, TokenVirtualizationEnabled,
&tokenInformation, sizeof(tokenInformation))) {
qWarning()<<getWinError();
return FALSE;
}
return TRUE;
}
#endif
#ifdef Q#u OS#u WIN32
#包括
QString getWinError()
{
DWORD dw=GetLastError();
LPWSTR lpMsgBuf=NULL;
格式化消息(
格式化\u消息\u分配\u缓冲区|
格式化来自\u系统的\u消息\u|
格式化\u消息\u忽略\u插入,
无效的
dw,
MAKELANGID(LANG_中立,SUBLANG_默认),
(LPWSTR)和lpMsgBuf,
0,空);
QString str=QString::fromChararray(lpMsgBuf);
本地免费(lpMsgBuf);
返回str;
}
bool disableVirtualStore()
{
处理令牌;
DWORD令牌信息=0;
if(!OpenProcessToken(GetCurrentProcess()、TOKEN\u ALL\u ACCESS和TOKEN)){
qWarning()退出时会做什么?有没有可能会删除目标?另外-您可以运行Process Monitor()实际上,检查发生了什么文件操作,或者只是调试Qt-在调试和查看Qt源代码时,有好几种情况实际上为我解决了一些问题。ON_EXIT在scope EXIT上执行括号中的代码。这绝对不是问题。我会查看Process Monitor,谢谢。我只是好奇:)有一件事似乎是interr测试-可能Qt无法在Windows上重命名accross dirs?发生这种情况时,move参数是true还是false?这两个值都会发生吗?刚刚检查了代码,在两个随机文件夹上工作正常。无法处理程序文件(这很有意义),请检查权限。再次感谢您建议使用Process Monitor,请参阅问题中的“我的编辑”。