QProcess, который переживет родителя для обновления - PullRequest
0 голосов
/ 07 сентября 2018

Было несколько сообщений по этому поводу, но я не испытывал то же самое. Я запускаю QT под Windows и пытаюсь запустить установщик, который перезапишет мое приложение. Я смог сделать это в C #, но, будучи новичком в QT, я не смог найти «секретный соус», который позволяет запущенному процессу пережить приложение.

Я попытался обновить процесс, потому что кто-то упомянул, что если они это сделают и не удалят QProcess, то он продолжает жить после того, как приложение запуска запуска исчезло. Я попробовал это, но как только мое приложение закрывается, все по-прежнему исчезает, хотя и с утечкой памяти. Я не могу продолжать работу приложения, потому что, в отличие от Linux, Windows не позволяет перезаписывать приложение, когда оно запущено. Кто-нибудь знает, как это сделать?
Что мне нужно сделать, это действительно просто:

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);

Ответы [ 3 ]

0 голосов
/ 07 сентября 2018

Быстрое и грязное решение - запустить исполняемый файл установщика внутри командного сценария Windows и обработать командный сценарий. Затем поместите 3-5-секундную команду «timeout» в начало скрипта, чтобы убедиться, что исходный исполняемый файл завершен.

0 голосов
/ 24 сентября 2018

Оказывается, что опубликованный мною метод работает, но он не будет работать, если вы запустите свое приложение в отладчике. По-видимому, в качестве меры предосторожности отладчик закрывает все порожденные потоки / процессы, когда приложение завершается. Спасибо всем за ответы !!

0 голосов
/ 07 сентября 2018

На самом деле, это работает как описано в ОП.

Это мой MCVE для демонстрации.

1) дочернее приложение 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;
}

Скомпилировано и протестировано:

$ g++ -std=c++11 -o testQProcessChild testQProcessChild.cc 

$ ./testQProcessChild 
testQProcessChild started.
Sleeping for three seconds...
testQProcessChild exits.

$

2) приложение Qt 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;
}

с файлом проекта testQProcessDetached.pro:

SOURCES = testQProcessDetached.cc

QT = widgets

Скомпилировано и протестировано:

$ qmake-qt5 testQProcessDetached.pro

$ make

$ ./testQProcessDetached
testQProcessChild started.
Sleeping for three seconds...
./testQProcessChild started.
testQProcessDetached exiting.

$ testQProcessChild exits.

Обратите внимание, что testQProcessDetached выходы, которые можно увидеть как приглашение $, появляются снова. Примерно через 3 секунды появляется вывод testQProcessChild exits. (чтобы доказать, что testQProcessChild переживает testQProcessDetached).

Я подозревал, что могут возникнуть проблемы с подключением к каналу. Поэтому после первой успешной попытки я прокомментировал вызовы close???Channel() и повторил тест & ndash; с тем же результатом, что и раньше.

Я тестировал в cygwin64 в Windows 10.


Образец testQProcessDetached.cc изменен, чтобы стать приложением с графическим интерфейсом:

#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();
}

Скомпилировано и протестировано:

$ qmake-qt5 testQProcessDetached.pro

$ make

$ ./testQProcessDetached

snapshot of testQProcessDetached

Нажмите

testQProcessChild started.
Sleeping for three seconds...
./testQProcessChild started.
testQProcessDetached exiting.

$ testQProcessChild exits.

Я скомпилировал второй пример на VS2013 с Qt для Windows. Это сработало.

snapshot of testQProcessDetached (compiled with VS2013)

Таким образом, мне пришлось заменить относительный путь ./testQProcessChild на абсолютный путь (хотя оба двоичных файла находились в одном каталоге). Как и об этом говорит OP, меня это не волновало.

...