Qt守护进程相关

16 篇文章 1 订阅

首先介绍一个功能函数,用于进程句柄的获取:

windows api manual:CreateToolhelp32Snapshot 函数 (tlhelp32.h) - Win32 apps | Microsoft Learn

#include <windows.h>
#include "tlhelp32.h"
#include <QString>

HANDLE GetProcessHandle(DWORD nID)
{
    return OpenProcess(PROCESS_ALL_ACCESS, FALSE, nID);
}
// 获取守护进程句柄
HANDLE GetProcessHandleByName(const QString &name)
{
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (INVALID_HANDLE_VALUE == hSnapshot)
    {
        return nullptr;
    }
    PROCESSENTRY32 pe = { sizeof(pe) };
    BOOL fOk;
    for (fOk = Process32First(hSnapshot, &pe); fOk; fOk = Process32Next(hSnapshot, &pe))
    {
        if (QString::fromWCharArray(pe.szExeFile) == name)
        {
            CloseHandle(hSnapshot);
            return GetProcessHandle(pe.th32ProcessID);
        }
    }
    return nullptr;
}

然后开线程进行检测(这里使用的是继承QThread重写run()的方式):

void DaemonTest::run()
{
    STARTUPINFOA si;
    //进程对象
    PROCESS_INFORMATION pi;
    //初始化
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));

    //构造cmd执行守护进程的字符串
    char pCmd[MAX_PATH_NUM] = { 0 };
    QFileInfo file(m_strFilePath + QDir::separator() + daemonName);
    QString strFilePath = file.filePath();
    strcat_s(pCmd, strFilePath.toStdString().c_str());


    while (m_bRunning)
    {
        //检查守护程序是否存在
        pi.hProcess = GetProcessHandleByName(daemonName);

        if (pi.hProcess == nullptr)
        {
            // 创建子进程,判断是否执行成功
            if (!CreateProcessA(NULL, pCmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
            {
                // 创建失败
            }
        }

        if (pi.hProcess != nullptr)
        {
            //无限等待子进程退出
            WaitForSingleObject(pi.hProcess, INFINITE);
            CloseHandle(pi.hProcess);
            CloseHandle(pi.hThread);
        }

        Sleep(100);
    }
}

开启守护进程的方法:

void StartDaemon(const QString &path)
{
    // 1、检测守护进程是否已经启动了
    if (GetProcessHandleByName(DAEMON_NAME) != nullptr)
    {
        return;
    }

    QString batFile = path + QDir::separator() + "StartDaemon.bat";
    if (QFile(batFile).exists())
    {
        QFile(batFile).remove();
    }

    QFile file(batFile);
    if (file.open(QFile::ReadWrite))
    {
        QString strParam = QString("@echo off \n start /d  \"%1\" HiDaemond.exe  \"%2\" \n exit").arg(QCoreApplication::applicationDirPath()).arg(QFileInfo(QCoreApplication::applicationFilePath()).fileName());
        file.write(strParam.toLocal8Bit());
        file.close();

        QProcess p;
        p.start("cmd.exe", QStringList() << "/c" << batFile);
        if (p.waitForStarted())
        {
            p.waitForFinished(2000);
            return;
        }
    }
    else
    {
        QString strAppPath = QApplication::applicationDirPath();
        QStringList arguments;
        {
            QFileInfo file(QApplication::applicationFilePath());
            arguments.append(file.fileName());
        }
        QFileInfo deamonFile(strAppPath + QDir::separator() + DAEMON_NAME);
        if (deamonFile.exists())
        {
            std::wstring operate = QString("runas").toStdWString();//临时提升管理员权限
            std::wstring path = QCoreApplication::applicationDirPath().toStdWString();
            std::wstring appName = QFileInfo(QCoreApplication::applicationFilePath()).fileName().toStdWString();;
            std::wstring file = deamonFile.filePath().toStdWString();
            int ret = reinterpret_cast<int>(ShellExecute(nullptr, operate.c_str(), file.c_str(), appName.c_str(), path.c_str(), SW_SHOWNORMAL));
            Q_UNUSED(ret)
        }
    }
}

杀死进程的方法:

void KillProcess(QString pName)
{
    QProcess p;
    QString c = "taskkill /im " + pName + " /f";    //exeFileName为要杀死的进程名
    p.execute(c);
    p.close();
}

管道通信方法:

// ******服务端******
void creatPipe()
{
    m_pHandle = CreateNamedPipe(PIPE_NAME, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, PIPE_MAXINSTANCES, 0, 0, 1000, NULL);
    if (INVALID_HANDLE_VALUE == m_pHandle)
    {
        CloseHandle(m_pHandle);
        // 创建管道失败
        m_pHandle = nullptr;
    }
}

void run()
{
    // 简单同步实现
    while (m_bRunning)
    {
        OVERLAPPED  ovlap;
        ZeroMemory(&ovlap, sizeof(OVERLAPPED));
        //2. 创建管道连接
        if (!ConnectNamedPipe(m_pHandle, &ovlap))
        {
            if (ERROR_IO_PENDING != GetLastError())
            {
                Sleep(100);
                continue;
            }
        }

        // 这个等待可能非常的久
        if (ReadFile(m_pHandle, m_readbuffer, 100, &m_readLenth, NULL) == TRUE)
        {
            emit parse();
        }
        DisconnectNamedPipe(m_pHandle);
    }
}

// ******客户端******
bool openPipe()
{
    if (m_pHandle)
    {
        CloseHandle(m_pHandle);
    }
    if (!WaitNamedPipe(PIPE_NAME, PIPE_TIMEOUT))
    {
        // 当前没有可利用的命名管道实例!
        return false;
    }

    m_pHandle = CreateFile(PIPE_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (INVALID_HANDLE_VALUE == m_pHandle)
    {
        // "打开命名管道失败!
        m_pHandle = NULL;
        return false;
    }
    return true;
}

void writeFile(PipeWriteType type, const QString & param)
{
    if (openPipe())
    {
        DWORD dwWriteLen = 0;
        QString strParam = QString("%1#%2").arg((int)type).arg(param);
        if (WriteFile(m_pHandle, strParam.toStdString().c_str(), strParam.length(), &dwWriteLen, NULL))
        {
            // 写入成功
        }
        CloseHandle(m_pHandle);
        m_pHandle = nullptr;
    }
    Sleep(200);
}

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值