Qt學習筆記:清除用QAxObject建立的Office程序
阿新 • • 發佈:2018-11-02
環境
系統: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程序的父程序不是同一個程序。
示例原始碼