Unable to launch QT desktop app from Qt Service using QProcess
-
HI,
I want to launch my QT desktop app when Windows is shutting down. In order to do this, I have created Qt service in which we want to do the followings;- Intercept/capture Windows/Mac shutdown process using WM_QUERYENDSESSION event capture. But, I am still unable to capture this event
- return result = 0; to halt shut down process
- launch QT desktop app using QProcess (unable to launch it from QT service, though same code able to launch the other instance of app from desktop app. I have able to run Qt service in user session, but still QT desktop app is not launched from service
Here is my code to capture WM_QUERYENDSESSION native event
class ShutdownEventFilter : public QAbstractNativeEventFilter { public: explicit ShutdownEventFilter(QObject *parent = nullptr); void launchApp(); protected: virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override; signals: }; ShutdownEventFilter::ShutdownEventFilter(QObject *parent) : QAbstractNativeEventFilter() {} bool ShutdownEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result) { if (eventType == "windows_generic_MSG") { MSG *msg = static_cast<MSG*>(message); if (msg->message == WM_QUERYENDSESSION) { Logging::getInstance()->writeLog("ShutdownEventFilter::nativeEventFilter::WM_QUERYENDSESSION------------blocing shutdown-----"); //-ShutdownBlockReasonCreate(msg->hwnd, L"Don't shutdown"); *result = 0; // Returning 1 allows the shutdown to proceed, 0 cancels it return true; // Consume the message, preventing further processing } else if (msg->message == WM_ENDSESSION) { Logging::getInstance()->writeLog("ShutdownEventFilter::nativeEventFilter::WM_ENDSESSION-----------shutting donw-----"); qApp->quit(); // Gracefully quit application } } return false; // handled by QT framework } void ShutdownEventFilter::launchApp() { Logging::getInstance()->writeLog("ShutdownEventFilter::launchApp"); QString program = "D:/Work/Qt_builds/inspirationalclips_Qt_6_8_0_MSVC2022_64bit-Debug/debug/inspirationalclips.exe"; QStringList arguments; // Add arguments if needed, e.g., arguments << "-flag" << "value"; QProcess *process = new QProcess(); QObject::connect(process, &QProcess::errorOccurred, [&](QProcess::ProcessError error) { qDebug() << "Process error:" << error << process->errorString(); Logging::getInstance()->writeLog("Process error:: " + process->errorString()); }); process->start(program, arguments); if (!process->waitForStarted()) { qDebug() << "Error starting application:" << process->errorString(); Logging::getInstance()->writeLog("Error starting application: " + process->errorString()); } // The process will continue to run independently // if you need to interact with it, use other QProcess methods Logging::getInstance()->writeLog("ShutdownEventFilter::launchApp App running-------------------"); }
Here is the code to register the event filter in QT service start function.
class MainService : public QtService<QApplication> { public: /** * @brief The constructor * @param argc * @param argv */ MainService(int argc, char **argv); /** * @brief The destructor */ ~MainService(); /** * @brief Start the service */ void start(); }; void MainService::start() { try { qApp->setApplicationName("InspirationalClipsService"); qDebug() << "InspirationalClips Service started!"; qDebug() << qApp->applicationDirPath(); ShutdownEventFilter shutdownfilter; qApp->installNativeEventFilter(&shutdownfilter); shutdownfilter.launchApp(); } catch(...) { qCritical() << "An unknown error in the start"; } }
-
@SGaist any expert comments on this! Thanks in advance for your time and cooperation.
-
I am using QT5.15.2 for Qt service and my desktop QT app is written in QT6.8.
-
-
Currently I am using Windows 10, but I need this functionality on Windows 11 and Mac as well.
-
@SGaist any expert comments on this! Thanks in advance for your time and cooperation.
@Sikander-Rafiq said in Unable to launch QT desktop app from Qt Service using QProcess:
@SGaist any expert comments on this!
No need to address people directly like this. If somebody has to say something he/she will do.
I see you have some error handling, but you do not say whether you see any errors printed.
-
No error printed, but desktop app not launched.
-
Hi,
I have added more error handling code to investigate what happened with new Process. The error logs shows that process is immediately terminated after started - don't know why. Investigating it.void ShutdownEventFilter::launchApp() { Logging::getInstance()->writeLog("ShutdownEventFilter::launchApp"); QString program = "D:/Work/Qt_builds/inspirationalclips_Qt_6_8_0_MSVC2022_64bit-Debug/debug/inspirationalclips.exe"; QStringList arguments; // Add arguments if needed, e.g., arguments << "-flag" << "value"; QProcess *process = new QProcess(); QObject::connect(process, &QProcess::errorOccurred, [&](QProcess::ProcessError error) { qDebug() << "Process error:" << error << process->errorString(); Logging::getInstance()->writeLog("Process error:: " + process->errorString()); }); QObject::connect(process, &QProcess::readyReadStandardOutput, [=]() { Logging::getInstance()->writeLog("Process::readyReadStandardOutput: " + process->readAllStandardOutput()); }); QObject::connect(process, &QProcess::readAllStandardError, [=]() { Logging::getInstance()->writeLog("Process::readAllStandardError: " + process->readAllStandardError()); }); QObject::connect(process, &QProcess::started, [=]() { Logging::getInstance()->writeLog("Process::started: "); }); QObject::connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), [&](int exitCode, QProcess::ExitStatus exitStatus) { QString strText = QString("processFinished: exitCode=%1").arg(exitCode); Logging::getInstance()->writeLog(strText); QString strExitStatus = QMetaEnum::fromType<QProcess::ExitStatus>().valueToKey(exitStatus); strText = QString("processFinished: exitStatus=%1").arg(strExitStatus); Logging::getInstance()->writeLog(strText); }); process->start(program, arguments); if (!process->waitForStarted()) { qDebug() << "Error starting application:" << process->errorString(); Logging::getInstance()->writeLog("Error starting application: " + process->errorString()); } QProcess::ProcessState state = process->state(); QString strState = QMetaEnum::fromType<QProcess::ProcessState>().valueToKey(state); QString strText = QString("ShutdownEventFilter::state state=%1").arg(strState); Logging::getInstance()->writeLog(strText); // The process will continue to run independently // if you need to interact with it, use other QProcess methods Logging::getInstance()->writeLog("ShutdownEventFilter::launchApp----------running fine-------"); }
Here are logs what I get:
2025-05-14 18:24:37: ShutdownEventFilter::launchApp
2025-05-14 18:24:37: Process::started:
2025-05-14 18:24:37: ShutdownEventFilter::state state=Running
2025-05-14 18:24:37: ShutdownEventFilter::launchApp----------running fine-------
2025-05-14 18:24:39: processFinished: exitCode=255
2025-05-14 18:24:39: processFinished: exitStatus=NormalExit -
Hi,
Did you properly deploy the Qt application you are starting ?
If not, it will not necessarily find its dependencies and thus fail to start. So first thing I would do is ensure that it can start from where you are calling it outside of Qt Creator. -
Hi,
Yes, the desktop app can be started directly if we paste its path
(i.e. D:/Work/Qt_builds/inspirationalclips_Qt_6_8_0_MSVC2022_64bit-Debug/debug/inspirationalclips.exe) in window explorer.The same code can launch another instance of the desktop app if called from the QT desktop app itself.
There is some issue due to QT service (as we want to launch it from service). As I said, Qt service is running in the current user's session (in which I login to Windows10).
One difference I have noted, when the app launched from QT app, then exitCode is 0 (as below)
2025-05-14 20:41:06: processFinished: exitCode = 0
2025-05-14 20:41:06: processFinished: exitStatus = NormalExitWhen this is launched from QT service, the exitCode is 255 (as below)
2025-05-14 20:43:46: processFinished: exitCode = 255
2025-05-14 20:43:46: processFinished: exitStatus = NormalExitAlthough exitStatus is the same in both cases (i.e., NormalExit)
My other question is does QT (especially QT 5.15.2) not supporting to capture WM_QUERYENDSESSION native event?
Thanks for your time to help!
-
I have logged process state changed event and few more. Here is the updated code and logs.
void ShutdownEventFilter::launchApp() { Logging::getInstance()->writeLog("ShutdownEventFilter::launchApp"); QString workingDir = "D:/Work/Qt_builds/inspirationalclips_Qt_6_8_0_MSVC2022_64bit-Debug/debug/"; QString program = "D:/Work/Qt_builds/inspirationalclips_Qt_6_8_0_MSVC2022_64bit-Debug/debug/inspirationalclips.exe"; QStringList arguments; // Add arguments if needed, e.g., arguments << "-flag" << "value"; QProcess *process = new QProcess(); //standard output: QObject::connect(process, &QProcess::readyReadStandardOutput, [=]() { Logging::getInstance()->writeLog("QProcess::readyReadStandardOutput: " + process->readAllStandardOutput()); }); QObject::connect(process, &QProcess::readAllStandardOutput, [=]() { QString strText = QString("QProcess::readAllStandardOutput: output = %1") .arg(QString::fromUtf8(process->readAllStandardOutput())); Logging::getInstance()->writeLog(strText); }); //standard errors: QObject::connect(process, &QProcess::errorOccurred, [&](QProcess::ProcessError error) { Logging::getInstance()->writeLog("QProcess::errorOccurred: " + process->errorString()); }); QObject::connect(process, &QProcess::readyReadStandardError, [=]() { QProcess::ProcessError procErr = process->error(); QString strErr = QMetaEnum::fromType<QProcess::ProcessError>().valueToKey(procErr); QString strText = QString("QProcess::readyReadStandardError: error = %1").arg(strErr); Logging::getInstance()->writeLog(strText); }); QObject::connect(process, &QProcess::readAllStandardError, [=]() { Logging::getInstance()->writeLog("QProcess::readAllStandardError: " + process->readAllStandardError()); }); QObject::connect(process, &QProcess::stateChanged, [&](QProcess::ProcessState state) { QString strState = QMetaEnum::fromType<QProcess::ProcessState>().valueToKey(state); QString strText = QString("QProcess::stateChanged: state = %1").arg(strState); Logging::getInstance()->writeLog(strText); }); QObject::connect(process, &QProcess::started, [=]() { Logging::getInstance()->writeLog("QProcess::started: -----------process started---"); }); QObject::connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), [&](int exitCode, QProcess::ExitStatus exitStatus) { QString strExitStatus = QMetaEnum::fromType<QProcess::ExitStatus>().valueToKey(exitStatus); QString strText = QString("QProcess::finished: exitCode = %1 exitStatus = %2") .arg(exitCode) .arg(strExitStatus); Logging::getInstance()->writeLog(strText); }); process->setWorkingDirectory(workingDir); process->start(program, arguments); if (!process->waitForStarted()) { qDebug() << "Error starting application:" << process->errorString(); Logging::getInstance()->writeLog("Error starting application: " + process->errorString()); } //print current state QProcess::ProcessState state = process->state(); QString strState = QMetaEnum::fromType<QProcess::ProcessState>().valueToKey(state); QString strText = QString("ShutdownEventFilter::state = %1").arg(strState); Logging::getInstance()->writeLog(strText); //print error if any: QProcess::ProcessError procErr = process->error(); QString strErr = QMetaEnum::fromType<QProcess::ProcessError>().valueToKey(procErr); strText = QString("ShutdownEventFilter::error = %1").arg(strErr); Logging::getInstance()->writeLog(strText); // The process will continue to run independently // if you need to interact with it, use other QProcess methods Logging::getInstance()->writeLog("ShutdownEventFilter::launchApp----------running------"); }
Here is the updated log file:
2025-05-15 15:05:49: ShutdownEventFilter::launchApp
2025-05-15 15:05:49: QProcess::stateChanged: state = Starting
2025-05-15 15:05:49: QProcess::stateChanged: state = Running
2025-05-15 15:05:49: QProcess::started: -----------process started---
2025-05-15 15:05:49: ShutdownEventFilter::state = Running
2025-05-15 15:05:49: ShutdownEventFilter::error = UnknownError
2025-05-15 15:05:49: ShutdownEventFilter::launchApp----------running------
2025-05-15 15:05:51: QProcess::stateChanged: state = NotRunning
2025-05-15 15:05:51: QProcess::finished: exitCode = 255 exitStatus = NormalExitThis logs shows process started and then goto ''Running' state and then Unknown error occurred and process terminated.
-