一、背景
一般情况下,程序退出时,它调用的所有子进程都会一起退出。但异常退出的时候,并非所有的子进程都能正确退出。所以我们的做法一般都是在程序启动的前来一次检查,将上次启动没有退出的子进程杀掉,然后再继续运行程序。
二、清理进程方式一
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");
|