QProcess that will outlive the parent for updating

南楼画角 提交于 2019-12-13 05:33:41

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!