How to Restart My Own Qt Application

how to restart an application in qt?

You can use QProcess::startDetached to run an instance of your application in a new process and detach from it. After that you should exit the application :

QProcess process;
process.startDetached("myApp",QStringList());

qApp->quit();

Here myApp is the name of the executable file of the application. On Windows it can be myApp.exe.

How to auto restart a Qt application when it crashes, within the same program?

Here's how you might do it using a single application that can act either as a monitor or as business logic. It's akin to Jon Harper's answer, except in code, not prose :)

Of Note

  1. The monitor should not instantiate a QApplication nor QGuiApplication: it has no UI. Otherwise, redundant running process indicators will appear on some platforms (i.e. OS X, Win 10).

  2. The monitor/business logic selection is achieved via setting an environment variable in the called process.

  3. Passing the monitor/business logic selection via command line arguments is problematic, as the command line switch would need to be filtered out -- doing that portably without running into corner cases is tricky.

  4. The monitor process forwards the console I/O of the business logic process, as well as the return code.

// https://github.com/KubaO/stackoverflown/tree/master/questions/appmonitor-37524491
#include <QtWidgets>
#include <cstdlib>
#if defined(Q_OS_WIN32)
#include <windows.h>
#else
static void DebugBreak() { abort(); }
#endif

static int businessLogicMain(int &argc, char **argv) {
QApplication app{argc, argv};
qDebug() << __FUNCTION__ << app.arguments();
QWidget w;
QHBoxLayout layout{&w};
QPushButton crash{"Crash"}; // purposefully crash for testing
QPushButton quit{"Quit"}; // graceful exit, which doesn't need restart
layout.addWidget(&crash);
layout.addWidget(&quit);
w.show();

QObject::connect(&crash, &QPushButton::clicked, DebugBreak);
QObject::connect(&quit, &QPushButton::clicked, &QCoreApplication::quit);
return app.exec();
}

static char const kRunLogic[] = "run__business__logic";
static char const kRunLogicValue[] = "run__business__logic";

#if defined(Q_OS_WIN32)
static QString getWindowsCommandLineArguments() {
const wchar_t *args = GetCommandLine();
bool oddBackslash = false, quoted = false, whitespace = false;
// skip the executable name according to Windows command line parsing rules
while (auto c = *args) {
if (c == L'\\')
oddBackslash ^= 1;
else if (c == L'"')
quoted ^= !oddBackslash;
else if (c == L' ' || c == L'\t')
whitespace = !quoted;
else if (whitespace)
break;
else
oddBackslash = false;
args++;
}
return QString::fromRawData(reinterpret_cast<const QChar*>(args), lstrlen(args));
}
#endif

static int monitorMain(int &argc, char **argv) {
#if !defined(Q_OS_WIN32)
QStringList args;
args.reserve(argc-1);
for (int i = 1; i < argc; ++i)
args << QString::fromLocal8Bit(argv[i]);
#endif
QCoreApplication app{argc, argv};
QProcess proc;
auto onFinished = [&](int retcode, QProcess::ExitStatus status) {
qDebug() << status;
if (status == QProcess::CrashExit)
proc.start(); // restart the app if the app crashed
else
app.exit(retcode); // no restart required
};
QObject::connect(&proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), onFinished);

auto env = QProcessEnvironment::systemEnvironment();
env.insert(kRunLogic, kRunLogicValue);
proc.setProgram(app.applicationFilePath()); // logic and monitor are the same executable
#if defined(Q_OS_WIN32)
SetErrorMode(SEM_NOGPFAULTERRORBOX); // disable Windows error reporting
proc.setNativeArguments(getWindowsCommandLineArguments()); // pass command line arguments natively
env.insert("QT_LOGGING_TO_CONSOLE", "1"); // ensure that the debug output gets passed along
#else
proc.setArguments(args);
#endif
proc.setProcessEnvironment(env);
proc.setProcessChannelMode(QProcess::ForwardedChannels);
proc.start();
return app.exec();
}

int main(int argc, char **argv) {
if (qgetenv(kRunLogic) != kRunLogicValue)
return monitorMain(argc, argv);
else
return qunsetenv(kRunLogic), businessLogicMain(argc, argv);
}

How do I restart my pyqt application?

Let's say you are in MainWindow. Define in the __init__

MainWindow.EXIT_CODE_REBOOT = -12345678  # or whatever number not already taken

Your slot restart() should contain:

qApp.exit( MainWindow.EXIT_CODE_REBOOT )

and your main:

currentExitCode = MainWindow.EXIT_CODE_REBOOT

while currentExitCode == MainWindow.EXIT_CODE_REBOOT:
a = QApplication(sys.argv)
w = MainWindow()
w.show()
currentExitCode = a.exec_()

return currentExitCode

[1] https://wiki.qt.io/How_to_make_an_Application_restartable


EDIT: Minimal working example

Instead of a signal/slot, I just re-implemented the keyPressedEvent method.

import sys
from PyQt4 import QtGui
from PyQt4.QtCore import Qt

class MainWindow(QtGui.QMainWindow):
EXIT_CODE_REBOOT = -123
def __init__(self,parent=None):
QtGui.QMainWindow.__init__(self, parent)

def keyPressEvent(self,e):
if (e.key() == Qt.Key_R):
QtGui.qApp.exit( MainWindow.EXIT_CODE_REBOOT )

if __name__=="__main__":
currentExitCode = MainWindow.EXIT_CODE_REBOOT
while currentExitCode == MainWindow.EXIT_CODE_REBOOT:
a = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
currentExitCode = a.exec_()
a = None # delete the QApplication object

How to restart a qt application after crashing?

create another qt application that runs your application.

#include <QApplication>
#include "QProcess"

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QProcess aProcess;
QString exe = "Your process name with exact path";
QByteArray myOut;
while(1)
{
aProcess.start(exe);
//aProcess.waitForStarted();
//myOut = aProcess.readAllStandardOutput();
//printf("%s",myOut.constData());
aProcess.waitForFinished(-1);

//QString output(aProcess.readAllStandardOutput());

myOut = aProcess.readAllStandardOutput();
printf("%s",myOut.constData());
}
return a.exec();
}

this program will restart your app when it crashed or closed

How to reboot PyQt5 application

The logic is to end the eventloop and launch the application an instant before it closes:

import sys
from PyQt5 import QtCore, QtWidgets

def restart():
QtCore.QCoreApplication.quit()
status = QtCore.QProcess.startDetached(sys.executable, sys.argv)
print(status)

def main():
app = QtWidgets.QApplication(sys.argv)

print("[PID]:", QtCore.QCoreApplication.applicationPid())

window = QtWidgets.QMainWindow()
window.show()

button = QtWidgets.QPushButton("Restart")
button.clicked.connect(restart)

window.setCentralWidget(button)

sys.exit(app.exec_())

if __name__ == "__main__":
main()


Related Topics



Leave a reply



Submit