环境
系统: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进程的父进程不是同一个进程。
示例源码