Qt 强杀进程、子进程(应用)的一种方式

一、背景

一般情况下,程序退出时,它调用的所有子进程都会一起退出。但异常退出的时候,并非所有的子进程都能正确退出。所以我们的做法一般都是在程序启动的前来一次检查,将上次启动没有退出的子进程杀掉,然后再继续运行程序。

二、清理进程方式一

1. 使用QProcess 执行杀进程命令:

QVector<DWORD> getCurPathSubProcessIdByProcessName(const QString &name)
{
    Q_UNUSED(name)
    QVector<DWORD> processIds;

    HANDLE hSnapshot;
    hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//拍摄进程快照
    qInfo() << __FUNCTION__ << "exeName" << name;

    if (hSnapshot == INVALID_HANDLE_VALUE) {    //拍摄快照失败
        qWarning() << __FUNCTION__ << "create snapshot faile";
        return processIds;
    }

    PROCESSENTRY32 ps;
    ZeroMemory(&ps, sizeof(PROCESSENTRY32));
    ps.dwSize = sizeof(PROCESSENTRY32);

    if (!Process32First(hSnapshot, &ps)) {
        qWarning() << __FUNCTION__ << "process32First faile";
        return processIds;
    }

    do {
        if (lstrcmpi(ps.szExeFile, name.toStdWString().data()) == 0) {
            std::wstring exePath = getProcessExePathByPid(ps.th32ProcessID);
            QDir dir;
            QString qExePath = dir.toNativeSeparators(QString::fromStdWString(exePath));
            QString appPath = dir.toNativeSeparators(
                                  QCoreApplication::applicationDirPath());
            qInfo() << __FUNCTION__ << exePath << qExePath << appPath;

            if (qExePath.startsWith(appPath)) {
                processIds.append(ps.th32ProcessID);
            }
        }
    } while (Process32Next(hSnapshot, &ps));

    qInfo() << __FUNCTION__ << "processIds :" << processIds;
    return processIds;
}

void ClearProcessByProcessName(const QString &strPrcessName)
{
    if (strPrcessName.isEmpty()) {
        return;
    }

    // 通过进程名获取和当前进程path一致的子进程
    QVector<DWORD> processIds = getCurPathSubProcessIdByProcessName(
                                    strPrcessName);

    for (int i = 0; i < processIds.size(); ++i) {
        QString strCmdLine = QString("TASKKILL /IM %1 /F").arg(processIds.at(i));
        int nExitCode = QProcess::execute(strCmdLine);
    }

}

2. 执行清理

    ClearProcessByProcessName("myapp.exe");

三、清理进程方式二

1. 使用进程管理快照,遍历查询名称

void ClearProcessByProcessName(const QString &strPrcessName)
{
    PROCESSENTRY32 pe32;
    pe32.dwSize=sizeof(pe32);
    HANDLE hProcessSnap=::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    BOOL bMore=::Process32First(hProcessSnap,&pe32);
    while(bMore) {
        int len= WideCharToMultiByte(CP_ACP, 0, pe32.szExeFile, wcslen(pe32.szExeFile),
                                     NULL, 0, NULL, NULL);
        char* m_char = new char[len+1];
        WideCharToMultiByte(CP_ACP, 0, pe32.szExeFile, wcslen(pe32.szExeFile),
                            m_char, len, NULL, NULL);
        m_char[len]='\0';

        if(strcmp(strPrcessName.toStdString().c_str(), m_char) == 0) {
            HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pe32.th32ProcessID);
            if(hProcess != NULL) {
                TerminateProcess(hProcess, 0);
            }
        }

        bMore=::Process32Next(hProcessSnap,&pe32);

        delete[] m_char;
    }
}

2. 执行清理 

    ClearProcessByProcessName("myapp.exe");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值