Qt学习笔记:清除用QAxObject创建的Office进程

环境

系统:Windows10 64位 家庭中文版
Qt版本:5.6.0 msvc2013 32位
编译器:Visual Studio 2013 专业版

目的

在Qt中,当程序非正常关闭时,用QAxObject创建的Office进程不会随着程序的关闭而关闭,导致进程残留。我们需要及时地清理这些进程,注意:不能不加区分地清理Office的进程,因为Office进程有可能是Qt程序创建的也有可能是Office本身创建的。

步骤

1.获取残留的Office进程的Pid,关键代码:

//根据进程名获取pid
QList<int> Widget::getListPidByName(const char *strName)
{
    QList<int> lstPid;
    HANDLE hProcess;
    PROCESSENTRY32 processEntry;
    processEntry.dwSize = sizeof(PROCESSENTRY32);
    BOOL bRet;
    //进行进程快照
    hProcess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); //TH32CS_SNAPPROCESS快照所有进程
    //开始进程查找
    bRet = Process32First(hProcess, &processEntry);
    //循环比较,得出ProcessID
    while(bRet)
    {
        QString temp = QString::fromWCharArray(processEntry.szExeFile);
        if(strcmp(strName, temp.toLocal8Bit()) == 0)
        {
            lstPid.append(processEntry.th32ProcessID);
        }
        bRet = Process32Next(hProcess, &processEntry);
    }
    return lstPid;
}

2.根据进程的Pid获取父Pid,关键代码:

//根据进程的Pid获取父Pid
DWORD Widget::getParentPidByPid(DWORD dwProcessId)
{
    LONG                        status = -1;
    DWORD                       dwParentPid = (DWORD)-1;
    HANDLE                      hProcess = NULL;
    PROCESS_BASIC_INFORMATION   processBasicInformation;

    PROCNTQSIP NtQueryInformationProcess = (PROCNTQSIP) GetProcAddress(
                GetModuleHandle(L"ntdll"), "NtQueryInformationProcess");

    if (NULL == NtQueryInformationProcess)
    {
        return (DWORD)-1;
    }
    // Get process handle
    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcessId);
    if (!hProcess)
    {
        return (DWORD)-1;
    }

    // Retrieve information
    status = NtQueryInformationProcess(hProcess,
                                       ProcessBasicInformation,
                                       (PVOID)&processBasicInformation,
                                       sizeof(PROCESS_BASIC_INFORMATION),
                                       NULL
                                       );

    //注意:这里要用32位的编译器,64位的编译器得到的不是0而是 -1073741820
    if (!status)
    {
        dwParentPid = processBasicInformation.InheritedFromUniqueProcessId;
    }

    CloseHandle(hProcess);

    return dwParentPid;
}

3.根据父Pid来决定要不要杀死这个进程,关键代码:

//杀死进程
void Widget::killProcess(const QList<int> &lstSubPid, const QList<int> &lstParentPid)
{
    int nParentPid = -1;
    //遍历子进程
    for (int i = 0; i < lstSubPid.count(); ++i)
    {
        //获取子进程的父进程
        nParentPid = getParentPidByPid(lstSubPid.at(i));
        //如果这个进程是由某个父进程创建的,则杀死
        if (lstParentPid.contains(nParentPid))
        {
            HANDLE hProcess = NULL;
            //打开目标进程
            hProcess = OpenProcess(PROCESS_TERMINATE,FALSE, lstSubPid.at(i));
            if (hProcess == NULL)
            {
                qDebug()<<"Open Process fAiled ,error:"<<GetLastError();
            }
            //结束目标进程
            DWORD ret = TerminateProcess(hProcess,0);
            if(ret == 0)
            {
                qDebug()<<"kill task faild,error:"<<GetLastError();
            }
            else
            {
                qDebug()<<"kill task success ------------------------------------------------";
            }
        }
    }
}

注意:这里这样做的原因是:用QAxObject创建的Office进程的父进程和用Office创建的Office进程的父进程不是同一个进程。
示例源码

猜你喜欢

转载自blog.csdn.net/chase_hung/article/details/83040075
今日推荐