C++ 当Qt应用程序崩溃时,如何在同一程序中自动重启?
当Qt应用程序异常崩溃时,是否有相对“标准”的设计来自动重启它 特定于Windows,我必须使用任何Windows服务吗?C++ 当Qt应用程序崩溃时,如何在同一程序中自动重启?,c++,windows,qt,process,restart,C++,Windows,Qt,Process,Restart,当Qt应用程序异常崩溃时,是否有相对“标准”的设计来自动重启它 特定于Windows,我必须使用任何Windows服务吗? 或者,如果我必须单独编写另一个程序,那么如何才能做到这一点?我不知道有什么标准的Qt方法可以在应用程序崩溃时重新启动它们。但是有一个很好的类,它使得编写一个主管/监控类非常容易。它被称为QProcess 您可以按如下方式启动此过程: monitorClass::startProcess(QString commandLine) // e.g. "c:\mytestapp.e
或者,如果我必须单独编写另一个程序,那么如何才能做到这一点?我不知道有什么标准的Qt方法可以在应用程序崩溃时重新启动它们。但是有一个很好的类,它使得编写一个主管/监控类非常容易。它被称为QProcess 您可以按如下方式启动此过程:
monitorClass::startProcess(QString commandLine) // e.g. "c:\mytestapp.exe param1 param2"
{
mp_Process = new QProcess(this);
mp_Process->start(commandLine);
mp_Process->waitForStarted();
// Start a timer
mp_Timer->start(1000);
}
然后,当计时器过期时(每秒钟一次,或其他任何时间)
注意
这实际上是伪代码,它不是一个可编译的示例-它只是向您大致展示了使用QProcess执行此操作有多容易…如果应用程序崩溃,它就完成了 您的监视器想法很好,可以通过使用来实现。使用“监视器”引导实际应用程序。为此,使用
QProcess
成员实现一个监控对象。在伪代码中:
class MonitorObject : public QObject
{
...
public Q_SLOTS:
void onStarted();
void onFinished(int, QProcess::ExitStatus);
...
private:
QProcess m_process;
}
然后在main
中:
- 在堆栈上创建一个
和一个监控对象QCoreApplication
- 向监视器对象发送排队信号,以便它知道主事件循环何时启动。您可以通过使用
:Qt::QueuedConnection
int main(...) { QCoreApplication app; MonitorObject monitor; ... // other initialization code here QMetaObject::invoke(&monitor, "onStarted", Qt::QueuedConnection); return app.exec(); }
监视器对象中
:
- 将
的QProcess
信号连接到finished
onFinished
- 调用
时,启动该过程MonitorObject::onStarted
- 当触发
信号时,根据发出的信号中的QProcess::finished
参数,重新启动有问题的程序或退出exitCode
QApplication
或QGuiApplication
:它没有UI。否则,在某些平台(即OS X、Win 10)上会出现冗余的运行过程指示器
//https://github.com/KubaO/stackoverflown/tree/master/questions/appmonitor-37524491
#包括
#包括
#如果已定义(Q_OS_WIN32)
#包括
#否则
静态void DebugBreak(){abort();}
#恩迪夫
静态int-businessLogicMain(int&argc,字符**argv){
QApplication app{argc,argv};
qDebug()您可以将应用程序设置为windows服务,并将“恢复”属性(当服务失败时)设置为“重新启动服务”。若要在Qt上创建windows服务,您可以尝试此项目:如果可以,我会为“代码,而不是散文”额外加1.:-)
int main(...)
{
QCoreApplication app;
MonitorObject monitor;
... // other initialization code here
QMetaObject::invoke(&monitor, "onStarted", Qt::QueuedConnection);
return app.exec();
}
// 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);
}