我们有SuspendThread函数,但大家发现,并没有SuspendProcess函数,其实,这跟windows操作系统时密切相关的(线程的变化非常快,我们无法预料)
下面我就提供一个SuspendProcess的版本,其实这跟我以前讲过的系统快照函数CreateToolhelp32Snapshot是有关的,要想写这个功能,必须列举某个进程的所有线程
typedef HANDLE (WINAPI * OPENTHREADFUN)(DWORD dwDesiredAccess,BOOL bInheritHandle,DWORD dwThreadId);
void CSuspendProcessDlg:: SuspendProcess(DWORD PID,BOOL fSuspend)
{
if(PID==0)
{
MessageBox("进程ID不能为0");
return;
}
HMODULE hKernel32 = ::GetModuleHandle(_T("kernel32.dll"));//由于我是在xp的vc6.0下测试的,系统没有OpenThread函数,只能用GetProcAddress函数自己获取函数地址了
OPENTHREADFUN pFun = (OPENTHREADFUN)GetProcAddress(hKernel32,_T("OpenThread"));
pFun(THREAD_ALL_ACCESS,FALSE,dwThreadId);//pFUn相当于OpenThread
CString temp;
m_threadid.ResetContent();
HANDLE hShot=CreateToolhelp32Snapshot(TH32CS_SNAPALL,0);//创建系统线程快照
int err=GetLastError();
if(hShot==INVALID_HANDLE_VALUE)
{
MessageBox("创建进程快照失败");
return;
}
THREADENTRY32 te={sizeof(te)};
BOOL bRet=Thread32First(hShot,&te);//Thread32First和Thread32Next是固定的用法
while(bRet)
{
if(te.th32OwnerProcessID==PID)//过滤出属于想要暂停的进程的线程ID
{
temp.Format("%d",te.th32ThreadID);
m_threadid.AddString(temp.GetBuffer(0));
if(fSuspend)
{
HANDLE hThread=pFun(THREAD_ALL_ACCESS,FALSE,te.th32ThreadID);//通过线程ID,打开线程内核对象,获取线程句柄
SuspendThread(hThread);//利用SuspendThread暂停线程,当所有的线程都暂停了,进程也就暂停了
CloseHandle(hThread);
}
else
{
HANDLE hThread=pFun(THREAD_ALL_ACCESS,FALSE,te.th32ThreadID);
ResumeThread(hThread);//如果fSuspend为false,表示恢复进程
CloseHandle(hThread);
}
}
bRet=Thread32Next(hShot,&te);
}
CloseHandle(hShot);
}
这里只是举了一个例子,但是这个函数不能总是运行,当枚举线程组时,线程可能创建和撤销,当我们调用CreateToolhelp32Snapshot,一个新线程可能出现在目标进程中,这个函数将无法暂停这个新出现的线程,当调用SuspendProcess来恢复进程的时候,我们可能恢复一个从未暂停过的线程,所以,我想,这个函数只能用于我们对之深刻了解的(自己编写的,里面线程比较稳定)的进程