C++ 在Windows QDir::mkpath和QFile::重命名报告成功,尽管失败

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(

我正在尝试将自动更新功能添加到我正在使用的应用程序中。我的解决方案在Linux上运行良好,但在Windows上我遇到了奇怪的问题

解包更新包后,我尝试使用以下功能将其移动到目标目录:

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,请参阅问题中的“我的编辑”。