QProcess 因 Qt 5.10.1 和 Windows 10 而失败

QProcess fails with Qt 5.10.1 and Windows 10

我最近静态编译了 Qt 5.10.1 (mingw32),下面的例程现在无法运行。我修改了代码以包含 windows cmd "c:\windows\system32\cmd.exe" 的完整路径,但这仍然不起作用。尝试使用 Windows 7 & 10。下面的代码适用于 Qt 5.6。它的工作是打开一个 Windows 终端。在 macOS 和 Linux 中打开控制台的类似代码有效。

注意:此行为是 Qt 5.8 中引入的错误,请参阅:

https://bugreports.qt.io/browse/QTBUG-57687

    QString commstr = adbdir+"cpath.bat";
    QFile file(commstr);

        if(!file.open(QFile::WriteOnly |
                      QFile::Text))
        {
            logfile("error creating cpath.bat!");
            QMessageBox::critical(this,"","Error creating bat file!");
            return;
        }

        QTextStream out(&file);
        out  << "set PATH=%PATH%;"+QDir::currentPath()+";"<< endl;

        file.flush();
        file.close();

        cstring = "cmd /k " +QDir::currentPath()+"/cpath.bat";
        QProcess::startDetached(cstring);

Qt 5.10 中正确的方法是将参数传递给 QProcess 程序,所以当你想 运行 cmd /k cpath.bat 那么程序是 cmd 并且参数是 /k xyz.bat。也根据错误报告 QTBUG-64662, Qt does start the process starts but to make it appear, that might be related to win32 API, so using QProcess::setCreateProcessArgumentsModifier could be used to show the shell as describer in QProcess Documentation。 所以在你的情况下:

#include "Windows.h"

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QProcess process;
    QString program = "cmd.exe";
    QStringList arguments = QStringList() << "/K" << QDir::currentPath()+"/cpath.bat";
    process->setCreateProcessArgumentsModifier([] (QProcess::CreateProcessArguments *args)
    {
        args->flags |= CREATE_NEW_CONSOLE;
        args->startupInfo->dwFlags &= ~STARTF_USESTDHANDLES;
    });
    process.start(program, arguments);
    process.waitForStarted();
    return app.exec();
}

并且为了创建分离进程,您可以继承 QProcess 并在它启动后将其分离,如下所示:

#include <QProcess>
#include <QString>
#include <QStringList>
#include <QDir>
#include "Windows.h"

class QDetachableProcess
        : public QProcess {
public:
    QDetachableProcess(QObject *parent = 0)
        : QProcess(parent) {
    }
    void detach() {
       waitForStarted();
       setProcessState(QProcess::NotRunning);
    }
};

int main(int argc, char *argv[]) {
    QDetachableProcess process;
    QString program = "cmd.exe";
    QStringList arguments = QStringList() << "/K" << QDir::currentPath()+"/cpath.bat";
    process.setCreateProcessArgumentsModifier(
                [](QProcess::CreateProcessArguments *args) {
        args->flags |= CREATE_NEW_CONSOLE;
        args->startupInfo->dwFlags &=~ STARTF_USESTDHANDLES;
    });
    process.start(program, arguments);
    process.detach();
    return 0;
}

注意:startDetached 的这种行为是 Qt 5.8 中引入的 Windows-specific Qt 错误。解决方法参考于:

https://bugreports.qt.io/browse/QTBUG-57687

   QProcess p;
        p.setProgram("cmd.exe");
        p.setArguments({"/k", QDir::currentPath()+"/cpath.bat"});
        p.setCreateProcessArgumentsModifier([] ( 
    QProcess::CreateProcessArguments
        *args) {
                args->flags &= ~CREATE_NO_WINDOW;
            });
        p.startDetached();