天天看點

Qt 程序守護程式(windows、linux)

一、windows環境下

1、程序查詢函數

processCount函數用于查詢系統所有運作的程序中該程序運作的數量,比如啟動了5個A程序,該函數查詢傳回的結果就為5。

windows下使用了API接口查詢程序資訊,該函數純C++無Qt庫相關代碼,注釋對代碼進行了詳細解釋。

int processCount(const char*  processName)
{
    int countProcess = 0;
    //CreateToolhelp32Snapshot 擷取系統中正在運作的程序資訊,線程資訊等
    HANDLE toolHelp32Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (((int)toolHelp32Snapshot) != -1)
    {
        PROCESSENTRY32 processEntry32;
        processEntry32.dwSize = sizeof(processEntry32);
        if(Process32First(toolHelp32Snapshot, &processEntry32))      //判斷程序擷取首程序是否存在
        {
            do
            {
                int iLen = 2 * wcslen(processEntry32.szExeFile);    //wcslen - 計算寬字元串的長度
                char* currentProcessName = new char[iLen + 1];
                wcstombs(currentProcessName, processEntry32.szExeFile, iLen + 1);    //将寬字元轉換成多字元
                if (strcmp(processName, currentProcessName) == 0)      //對比程序名
                    countProcess++;
                delete []currentProcessName;
            }while (Process32Next(toolHelp32Snapshot, &processEntry32));     //程序擷取函數,擷取下一個程序名
        }
        //關閉一個核心對象。其中包括檔案、檔案映射、程序、線程、安全和同步對象等。
        CloseHandle(toolHelp32Snapshot);
    }
    return countProcess;
}      

2、程序守護代碼

程序守護其實就是使用一個程序去定時查詢另外一個被守護的程序是否存在,不存在則需要啟動該程序。代碼如下,運作時,首先需要擷取被守護的程序APP,使用讀取配置檔案的方式,如果配置檔案不存在(首次啟動該代碼),則需要選擇被守護的程序,然後将選擇的APP路勁存入配置檔案,供下次啟動讀取使用。

#include <QApplication>
#include <QFileDialog>
#include <QSettings>
#include <windows.h>
#include <QDebug>
#include <QDateTime>

int main(int argc, char *argv[])
{
    QSettings sets("sys.ini", QSettings::IniFormat);
    QString targetExePath = sets.value(KEY_EXE_PATH).toString();
    if ("" == targetExePath)
    {
        //首次需要選擇 被守護的程序
        QString exepath = QFileDialog::getOpenFileName(nullptr, "選擇程式", "D:/", "Exe files (*.exe)");
        if ("" != exepath)
            sets.setValue(KEY_EXE_PATH, exepath);       //寫入配置檔案
    }
    while (1)        //死循環,不斷查詢判斷
    {
        //targetExePath = sets.value(KEY_EXE_PATH).toString();
        QString exeName = targetExePath.split('/').last();

        QDateTime strtTime = QDateTime::currentDateTime();
        int countProcess = processCount(exeName.toStdString().c_str());   // 查詢該程序運作數量
        qDebug()<<"use times for Query process:"<<strtTime.msecsTo(QDateTime::currentDateTime())<<"(ms)   countProcess:"<<countProcess;
        if (countProcess == 0)
            system(targetExePath.toStdString().c_str());        //關閉狀态 重新開機程序,注意:這裡實際運作會阻塞在這裡,一直等到被守護的線程結束。
       Sleep(3000);
    }
}      

二、linux環境下

1、程序查詢函數

原理: 使用 popen函數 + pidof指令 查詢對應程序的pid,該方法的缺點就是不能像windows那樣讀取所有程序名進而擷取該程序運作的數量。是以,如果一個程式加載多個程序(同程式程序名相同,pid不同),使用該方法隻能擷取最後一個啟動的程序pid。

pid_t getProcessPidByName(const char *proc_name)
{
     FILE *fp;
     char buf[100];
     char cmd[200] = {'\0'};
     pid_t pid = -1;
     sprintf(cmd, "pidof %s", proc_name);
     if((fp = popen(cmd, "r")) != NULL)
     {
         if(fgets(buf, 255, fp) != NULL)
             pid = atoi(buf);
     }
     pclose(fp);
     return pid;
}      
int main(int argc, char *argv[])
{
    while(1)
    {
        if(getProcessPidByName("qtcreator") == -1)
        {
            printf("open APP qtcreator...");
            system("qtcreator &");        //啟動軟體
        }
        sleep(5);        //需要大于軟體啟動時間
    }
    return 0;
}