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();
我最近静态编译了 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();