• 48阅读
  • 0回复

用Qt打造永远运行的程序/守护进程/程序启动器/实时监测程序运行/后台运行 [复制链接]

上一主题 下一主题
离线liudianwu
 

图酷模式  只看楼主 倒序阅读 楼主  发表于: 昨天 07:38


## 一、前言说明
最近有个定制需求,希望程序能够一直运行,比如在windows上运行的程序,很可能无法保证不出故障崩溃,有时候可能是程序内部处理异常导致的崩溃,比如有些数据解析没有考虑到一些极端的情况,还有就是用户主动关闭了程序,可能是误关闭,而有些程序,又必须7*24小时运行,所以必须要有个守护进程,能够实时监测程序的运行情况,一旦发现程序死机或者不存在了,则重启程序。

在一些嵌入式板子上,有个看门狗的功能,打开看门狗驱动后,定时喂狗,如果程序死了或者不存在了,则喂狗超时,会触发硬件重启,这个比较彻底。如果用纯软件实现呢,一般不会去重启系统,尽管执行对应的重启指令也可以做到,一般会重启程序,第一步是先kill掉程序,因为可能程序还在只是死机了,第二步是重新启动程序,在某些环境中,有些程序可能还有托盘图标残留,所以可能还需要结束桌面进程,然后再启动桌面进程,这样残留的托盘图标也会清除,因为很多时候意外关闭程序,对应托盘图标不会退出的。

使用软件来实现程序启动器,一般都会采用udp通信的方式,软件端监听对应端口,收到hello指令后,回复自己的程序名称加上ok数据,守护端这边不断的发hello指令,收到对应ok后就表示正常,将错误计数清零,每一轮没有收到ok则错误计数累加,连续超过多少次比如3次则认为程序死了,然后就去执行重启程序,为什么用udp,因为无连接,资源占用极低,而且基本上都是本机内部通信,也就是127.0.0.1这个地址进行交互,所以几乎不会给现有的程序造成负担。

## 二、效果图

window.open('http://www.qtcn.org/bbs/attachment/Mon_2509/44_110085_5ca9da580e22da5.jpg?91');" style="max-width:700px;max-height:700px;" onload="if(is_ie6&&this.offsetWidth>700)this.width=700;" >


## 三、代码使用
```cpp
#include "frmlivetool.h"
#include "ui_frmlivetool.h"
#include "qthelper.h"
#include "liveserver.h"
#include "trayicon.h"

frmLiveTool::frmLiveTool(QWidget *parent) : QWidget(parent), ui(new Ui::frmLiveTool)
{
    ui->setupUi(this);
    this->initForm();
    QtHelper::setFormInCenter(this);
    on_btnStart_clicked();
}

frmLiveTool::~frmLiveTool()
{
    delete ui;
}

void frmLiveTool::closeEvent(QCloseEvent *e)
{
    if (QtHelper::showMessageBoxQuestion("确定要退出吗? 退出后所有服务将停止!") != QMessageBox::Yes) {
        e->ignore();
        return;
    }

    if (AppConfig::UseTray) {
        TrayIcon::Instance()->setVisible(false);
    }
}

void frmLiveTool::showEvent(QShowEvent *)
{
    AppConfig::HideTray = false;
    AppConfig::writeConfig();
}

void frmLiveTool::changeEvent(QEvent *)
{
    //启用托盘服务则隐藏主界面
    if (this->windowState() == Qt::WindowMinimized) {
        if (AppConfig::UseTray) {
            this->hide();
            AppConfig::HideTray = true;
            AppConfig::writeConfig();
            TrayIcon::Instance()->showMessage("提示", "程序最小化到后台运行!");
        }
    }
}

void frmLiveTool::initForm()
{
    //设置托盘图标和主窗体
    if (AppConfig::UseTray) {
        TrayIcon::Instance()->setIcon(":/main.ico");
        TrayIcon::Instance()->setMainWidget(this);
        TrayIcon::Instance()->setVisible(true);
    }

    //设置开机启动
    QtHelper::runWithSystem(AppConfig::AutoRun);

    ui->txtAppName->setText(AppConfig::AppName);
    ui->labCount->setText(QString("已重启 %1 次").arg(AppConfig::ReStartCount));
    ui->labInfo->setText(QString("最后一次重启在 %1").arg(AppConfig::ReStartTime));

    connect(LiveServer::Instance(), SIGNAL(reStart()), this, SLOT(reStart()));
    LiveServer::Instance()->setPara(AppConfig::AppPath, AppConfig::AppName, AppConfig::AppPort, AppConfig::MaxCount, AppConfig::UpdateDesk);
}

void frmLiveTool::reStart()
{
    AppConfig::ReStartCount++;
    AppConfig::ReStartTime = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
    AppConfig::writeConfig();

    ui->labCount->setText(QString("已重启 %1 次").arg(AppConfig::ReStartCount));
    ui->labInfo->setText(QString("最后一次重启在 %1").arg(AppConfig::ReStartTime));
}

void frmLiveTool::on_btnOk_clicked()
{
    AppConfig::AppName = ui->txtAppName->text();
    if (AppConfig::AppName.isEmpty()) {
        QMessageBox::critical(this, "提示", "应用程序名称不能为空!");
        ui->txtAppName->setFocus();
        return;
    }

    AppConfig::writeConfig();
    ui->btnStart->setEnabled(true);
    LiveServer::Instance()->setPara(AppConfig::AppPath, AppConfig::AppName, AppConfig::AppPort, AppConfig::MaxCount, AppConfig::UpdateDesk);
}

void frmLiveTool::on_btnStart_clicked()
{
    if (ui->btnStart->text() == "开始") {
        LiveServer::Instance()->start(AppConfig::Interval);
        ui->btnStart->setText("暂停");
    } else {
        LiveServer::Instance()->stop();
        ui->btnStart->setText("开始");
    }
}

void frmLiveTool::on_btnReset_clicked()
{
    AppConfig::ReStartCount = -1;
    this->reStart();
    QMessageBox::information(this, "提示", "重置配置文件成功!");
}
```

## 四、相关地址
1. 国内站点:[https://gitee.com/feiyangqingyun](https://gitee.com/feiyangqingyun)
2. 国际站点:[https://github.com/feiyangqingyun](https://github.com/feiyangqingyun)
3. 个人作品:[https://blog.csdn.net/feiyangqingyun/article/details/97565652](https://blog.csdn.net/feiyangqingyun/article/details/97565652)
4. 文件地址:[https://pan.baidu.com/s/1ZxG-oyUKe286LPMPxOrO2A](https://pan.baidu.com/s/1ZxG-oyUKe286LPMPxOrO2A) 提取码:o05q  文件名:bin_map.zip
欢迎关注微信公众号:Qt实战/Qt入门和进阶(各种开源作品、经验整理、项目实战技巧,专注Qt/C++软件开发,视频监控、物联网、工业控制、嵌入式软件、国产化系统应用软件开发) QQ:517216493  WX:feiyangqingyun  QQ群:751439350
快速回复
限100 字节
 
上一个 下一个