问题
There have been several posts regarding this, but I've not experienced the same. I'm running QT under Windows and trying to start an installer that will overwrite my app. I've been able to do this in C#, but being new to QT, I've not been able to find the "secret sauce" that allows the the launched process to outlive the app.
I've tried newing the process because someone mentioned that if they do that and don't delete the QProcess, then it was living on after the launcher app went away. I tried this, but as soon as my app quits, everything still goes away, albeit with a memory leak. I can't keep the app going because unlike Linux, Windows won't let you overwrite the application when it's running. Does anyone know how to do this?
What I need to do is really simple:
QString filename = ""full/path/to/installer.exe";
QProcess * pProcess = new QProcess();
int result = pProcess->startDetached(filename);
if (result)
QCoreApplication::quit();
else
QMessageBox::warning(this,tr("Oh NO!!"),tr("Couldn't start the installer!!!"),QMessageBox::Ok);
回答1:
Actually, it works as described by OP.
This is my MCVE to demonstrate.
1) a child application testQProcessChild.cc
:
#include <chrono>
#include <thread>
#include <iostream>
int main()
{
std::cout << "testQProcessChild started.\n"
<< "Sleeping for three seconds...\n";
std::this_thread::sleep_for(std::chrono::seconds(3));
std::cout << "testQProcessChild exits.\n";
return 0;
}
Compiled and tested:
$ g++ -std=c++11 -o testQProcessChild testQProcessChild.cc
$ ./testQProcessChild
testQProcessChild started.
Sleeping for three seconds...
testQProcessChild exits.
$
2) the Qt application testQProcessDetached.cc
:
#include <QtWidgets>
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QProcess qProcess;
//qProcess.closeWriteChannel();
//qProcess.closeReadChannel(QProcess::StandardOutput);
//qProcess.closeReadChannel(QProcess::StandardError);
if (qProcess.startDetached(QString::fromLatin1("./testQProcessChild"))) {
qDebug() << "./testQProcessChild started.";
} else {
qDebug() << "Cannot start ./testQProcessChild!";
}
qDebug() << "testQProcessDetached exiting.";
return 0;
}
with project file testQProcessDetached.pro
:
SOURCES = testQProcessDetached.cc
QT = widgets
Compiled and tested:
$ qmake-qt5 testQProcessDetached.pro
$ make
$ ./testQProcessDetached
testQProcessChild started.
Sleeping for three seconds...
./testQProcessChild started.
testQProcessDetached exiting.
$ testQProcessChild exits.
Please note, that testQProcessDetached
exits which can be seen as the prompt $
appears again. Round about 3 seconds later the output testQProcessChild exits.
appears (to prove that testQProcessChild
outlives testQProcessDetached
).
I suspected that channel connections could be an issue. Hence, after first successful attempt, I commented the close???Channel()
calls and repeated the test – with the same result as before.
I've tested in cygwin64 on Windows 10.
The sample testQProcessDetached.cc
modified to become a GUI application:
#include <QtWidgets>
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QPushButton qBtn(QString::fromUtf8("Start Child"));
qBtn.show();
QObject::connect(&qBtn, &QPushButton::clicked,
[&](bool) {
QProcess qProcess;
//qProcess.closeWriteChannel();
//qProcess.closeReadChannel(QProcess::StandardOutput);
//qProcess.closeReadChannel(QProcess::StandardError);
if (qProcess.startDetached(QString::fromLatin1("./testQProcessChild"))) {
qDebug() << "./testQProcessChild started.";
QApplication::quit();
} else {
qDebug() << "Cannot start ./testQProcessChild!";
}
});
return app.exec();
}
Compiled and tested:
$ qmake-qt5 testQProcessDetached.pro
$ make
$ ./testQProcessDetached
Click
testQProcessChild started.
Sleeping for three seconds...
./testQProcessChild started.
testQProcessDetached exiting.
$ testQProcessChild exits.
I compiled the second sample on VS2013 with Qt for Windows. It worked as well.
Thereby, I had to replace the relative path ./testQProcessChild
with the absolute path (although both binaries resided in the same directory). As this is stated by OP as well, I didn't care about this.
回答2:
A quick and dirty solution is to run your installer executable inside of a Windows command script and QProcess the command script. Then put a 3-5 second 'timeout' command at the start of the script to ensure that the original executable has finished.
回答3:
It turns out that the method I posted does work, but it won't work if you run your app in the debugger. Apparently, as a safety precaution, the debugger closes all spawned threads/processes when the app terminates. Thank you all for your answers!!
来源:https://stackoverflow.com/questions/52225229/qprocess-that-will-outlive-the-parent-for-updating