Search code examples
qtexitrestart

Restarting Application after Updater on Qt


After a successful update, I am using the following logic to restart the application:

   QString appName = QApplication::instance()->applicationName();
   QString appDir =  QApplication::instance()->applicationFilePath();
   QStringList arguments = QApplication::instance()->arguments();

   QProcess::startDetached( appName, arguments, appDir );

   //quit the current application
   QApplication::instance()->exit();

It starts the new application and also exits both the application. From Qt, I understand that the new process would live even after exiting the calling process. Am I missing something here?


Solution

  • Here are the problems:

    1. Your appName is not guaranteed not to be empty, and it's not guaranteed to be same as the name of the executable. In any case, startDetached() expects a full path to the executable.

    2. Your appDir isn't -- it's the full file path of the executable.

    3. The last argument to startDetached() is the working directory. You can simply use QDir::currentPath() for that.

    4. All of the QApplication methods that you are calling are static. You don't need to use the instance().

    To update your application, you could:

    1. Rename the currently running executable to some other name.

    2. Write the new executable under the original name.

    3. Start as as below.

    This would work on both Windows and Unices, as long as your application had sufficient administrative rights -- usually it won't, though, so you need a separate updater with sufficient access rights. The updater would need to signal the application to restart itself at user's convenience. It's probably not very nice to forcibly restart the application while the user is busy using it.

    Below is a working example:

    #include <QtWidgets>
    
    void start() {
        auto app = QCoreApplication::applicationFilePath();
        auto arguments = QCoreApplication::arguments();
        auto pwd = QDir::currentPath();
        qDebug() << app << arguments << pwd;
        QProcess::startDetached(app, arguments, pwd);
        QCoreApplication::exit();
    }
    
    int main(int argc, char **argv) {
        QApplication app{argc, argv};
        QPushButton button{QStringLiteral("Spawn")};
        Starter starter;
        QObject::connect(&button, &QPushButton::clicked, &start);
        button.show();
        app.exec();
    }