#pragma execution_character_set("utf-8")
#include "frmmain.h"
#include "ui_frmmain.h"
#include "qtimer.h"
#include "qudpsocket.h"
#include "qsharedmemory.h"
#include "qprocess.h"
#include "qdatetime.h"
#include "qapplication.h"
#include "qdesktopservices.h"
#include "qmessagebox.h"
#if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
#include "qstandardpaths.h"
#endif
#include "app.h"
frmMain::frmMain(QWidget *parent) : QWidget(parent), ui(new Ui::frmMain)
{
ui->setupUi(this);
this->initForm();
}
frmMain::~frmMain()
{
delete ui;
}
void frmMain::changeEvent(QEvent *event)
{
//隐藏当前界面,最小化到托盘
if(event->type() == QEvent::WindowStateChange) {
if(windowState() & Qt::WindowMinimized) {
hide();
}
}
QWidget::changeEvent(event);
}
void frmMain::initForm()
{
count = 0;
ok = false;
//每秒钟定时询问心跳
timerHeart = new QTimer(this);
timerHeart->setInterval(2000);
connect(timerHeart, SIGNAL(timeout()), this, SLOT(sendHearData()));
//从6050端口开始,如果绑定失败则将端口加1,直到绑定成功
udp = new QUdpSocket(this);
int port = 6050;
while(!udp->bind(port)) {
port++;
}
connect(udp, SIGNAL(readyRead()), this, SLOT(readData()));
if (App::TargetAppName.isEmpty()) {
ui->btnStart->setText("启动");
ui->btnStart->setEnabled(false);
timerHeart->stop();
} else {
ui->btnStart->setText("暂停");
ui->btnStart->setEnabled(true);
timerHeart->start();
}
ui->txtAppName->setText(App::TargetAppName);
ui->txtAppName->setFocus();
}
void frmMain::sendHearData()
{
udp->writeDatagram("hello", QHostAddress::LocalHost, App::TargetAppPort);
//判断当前是否没有回复
if (!ok) {
count++;
} else {
count = 0;
ok = false;
}
//如果超过规定次数没有收到心跳回复,则超时重启
if (count >= App::TimeoutCount) {
timerHeart->stop();
QSharedMemory mem(App::TargetAppName);
if (!mem.create(1)) {
killApp();
}
QTimer::singleShot(1000 , this, SLOT(killOther()));
QTimer::singleShot(3000 , this, SLOT(startApp()));
QTimer::singleShot(4000 , this, SLOT(startExplorer()));
}
}
void frmMain::killApp()
{
QProcess *p = new QProcess;
p->start(QString("taskkill /im %1.exe /f").arg(App::TargetAppName));
}
void frmMain::killOther()
{
QProcess *p = new QProcess;
p->start(QString("taskkill /im %1.exe /f").arg("WerFault"));
//重建缓存,彻底清除托盘图标
if (App::ReStartExplorer) {
QProcess *p1 = new QProcess;
p1->start("taskkill /f /im explorer.exe");
}
}
void frmMain::startApp()
{
if (ui->btnStart->text() == "开始" || ui->btnStart->text() == "启动") {
count = 0;
return;
}
QProcess *p = new QProcess;
p->start(QString("\"%1/%2.exe\"").arg(qApp->applicationDirPath()).arg(App::TargetAppName));
count = 0;
ok = true;
timerHeart->start();
App::ReStartCount++;
App::ReStartLastTime = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
App::writeConfig();
ui->labCount->setText(QString("已重启 %1 次").arg(App::ReStartCount));
ui->labInfo->setText(QString("最后一次重启在 %1").arg(App::ReStartLastTime));
}
void frmMain::startExplorer()
{
//取得操作系统目录路径,指定操作系统目录下的explorer程序,采用绝对路径,否则在64位操作系统下无效
#if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
QString str = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation);
#else
QString str = QDesktopServices::storageLocation(QDesktopServices::ApplicationsLocation);
#endif
if (App::ReStartExplorer) {
str = QString("%1\\Windows\\explorer.exe").arg(str.mid(0, 2));
QProcess *p = new QProcess(this);
p->start(str);
}
}
void frmMain::readData()
{
QByteArray tempData;
do {
tempData.resize(udp->pendingDatagramSize());
udp->readDatagram(tempData.data(), tempData.size());
QString data = QLatin1String(tempData);
if (data.right(2) == "OK") {
count = 0;
ok = true;
}
} while (udp->hasPendingDatagrams());
}
void frmMain::on_btnOk_clicked()
{
App::TargetAppName = ui->txtAppName->text();
if (App::TargetAppName == "") {
QMessageBox::critical(this, "提示", "应用程序名称不能为空!");
ui->txtAppName->setFocus();
return;
}
App::writeConfig();
ui->btnStart->setEnabled(true);
}
void frmMain::on_btnStart_clicked()
{
count = 0;
if (ui->btnStart->text() == "暂停") {
timerHeart->stop();
ui->btnStart->setText("开始");
} else {
timerHeart->start();
ui->btnStart->setText("暂停");
}
}
void frmMain::on_btnReset_clicked()
{
App::ReStartCount = 0;
App::ReStartLastTime = "2019-01-01 12:00:00";
App::writeConfig();
ui->txtAppName->setText(App::TargetAppName);
ui->labCount->setText(QString("已重启 %1 次").arg(App::ReStartCount));
ui->labInfo->setText(QString("最后一次重启在 %1").arg(App::ReStartLastTime));
QMessageBox::information(this, "提示", "重置配置文件成功!");
}
没有合适的资源?快使用搜索试试~ 我知道了~
Qt编写守护进程
共24个文件
cpp:7个
h:5个
pro:3个
3星 · 超过75%的资源 需积分: 48 199 下载量 60 浏览量
2019-03-02
14:56:06
上传
评论 8
收藏 64KB ZIP 举报
温馨提示
没有任何人敢保证自己写的程序没有任何BUG,尤其是在商业项目中,程序量越大,复杂度越高,出错的概率越大,尤其是现场环境千差万别,和当初本地电脑测试环境很可能不一样,有很多特殊情况没有考虑到,如果需要保证程序7*24小时运行,则需要想一些办法能够让程序死了能够活过来,在嵌入式linux上,大部分会采用看门狗的形式来处理,程序打开看门狗驱动后,定时喂狗,一旦超过规定的时间,则硬件软复位等。这种方式相对来说比较可靠,如果需要在普通PC机上运行怎办呢?本篇文章提供一个软件实现守护进程的办法,原理就是udp通信,单独写个守护进程程序,专门负责检测主程序是否存在,不存在则启动。主程序只需要启动live类监听端口,收到hello就回复ok就行。 为了使得兼容任意程序,特意提炼出来共性,增加了多种设置。 1:可设置检测的程序名称。 2:可设置udp通信端口。 3:可设置超时次数。 4:自动记录已重启次数。 5:自动记录最后一次重启时间。 6:是否需要重新刷新桌面。 7:可重置当前重启次数和最后重启时间。 8:自动隐藏的托盘运行或者后台运行。 9:提供界面设置程序名称已经开启和暂停服务。
资源推荐
资源详情
资源评论
收起资源包目录
live.zip (24个子文件)
live
livedemo
applive.cpp 2KB
frmmain.ui 495B
applive.h 446B
frmmain.h 284B
livedemo.pro.user 23KB
frmmain.cpp 201B
main.cpp 880B
livedemo.pro 570B
live.pro 82B
snap
QQ截图20190302141129.png 16KB
QQ截图20190302141124.png 11KB
QQ截图20190302141147.png 13KB
livetool
trayicon.h 2KB
main.ico 66KB
app.cpp 2KB
frmmain.ui 3KB
main.qrc 92B
livetool.pro 595B
frmmain.h 833B
frmmain.cpp 5KB
main.cpp 1KB
trayicon.cpp 2KB
livetool.pro.user 29KB
app.h 849B
共 24 条
- 1
资源评论
- 深宫大院2020-01-08一般,还可以吧 能起到守护的作用
- 小岗哥哥2019-11-14代码比较工整,但是守护进程这么写意义不大,核心就是用qprocess去杀、起进程,然后两个demo间用udp通讯,感觉通讯多此一举,可直接在起进程时获取id,记录下来管理起来。
feiyangqingyun
- 粉丝: 5w+
- 资源: 186
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功