您的位置:首页 > 其它

MFC 关闭另一个指定的进程问题

2013-12-02 14:38 281 查看
方法有好几种:

最简单的就是获得窗口的句柄之后,那么可以使用向该窗体发送WM_CLOSE消息的进行进程的关闭。 

下面是几种比较强制杀死的方法:

 

结束进程的函数为BOOL TerminateProcess(

  HANDLE hProcess,

  UINT uExitCode

);

这个函数要求一个进程的handle。而进程的handle可以用进程的ID通过下面的函数来得到。

HANDLE OpenProcess(

  DWORD dwDesiredAccess,

  BOOL bInheritHandle,

  DWORD dwProcessId

);

而这个函数又需要进程的ID,而进程的ID可以通过进程name来的到,也即是通过任务管理器里面的进程的名字来得到。

至于如何通过进程的name,如,QQ.exe。来得到进程的ID则可以用如下方法。

思路如下,通过如下函数得到系统进程的一个快照。

HANDLE WINAPI CreateToolhelp32Snapshot(

  DWORD dwFlags,

  DWORD th32ProcessID

);

通过如下的两个函数来遍历其中每个进程,比较他们的进程的name,最后得到进程的ID。

BOOL WINAPI Process32First(

  HANDLE hSnapshot,

  LPPROCESSENTRY32 lppe

);

BOOL WINAPI Process32Next(

  HANDLE hSnapshot,

  LPPROCESSENTRY32 lppe

);

有了ID那么就可以执行结束进程的操作了。参考函数如下:

 

DWORD GetProcessIdFromName(LPCTSTR name) 

       PROCESSENTRY32 pe; 
       DWORD id = 0; 
//请参考msdn,主要是获得windows当前的任务的一个snap(快照)。 
       HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); 
       pe.dwSize = sizeof(PROCESSENTRY32); 
       //检索上一步获得的windows的快照的每个进程。First ,next 函数 
       if(!Process32First(hSnapshot,&pe)) 
              return 0; 
       CString name1,name2; 
 
       do 
       { 
              pe.dwSize = sizeof(PROCESSENTRY32); 
              name1=pe.szExeFile; 
              name2=name; 
              name1.MakeUpper(); 
              name2.MakeUpper(); 
//其中参数pe里面有进程信息如name,即在任务管理器里面看到的名字,如qq.exe 
if(strcmp(name1.GetBuffer(0),name2.GetBuffer(0))   ==   0) 
              { 
                     //记下这个ID,也及时我们要得到的进程的ID 
                     id   =   pe.th32ProcessID; 
                     break
              } 
 
              if(Process32Next(hSnapshot,&pe)==FALSE)  
                     break
       } while(1); 
       CloseHandle(hSnapshot); 
       return id; 

由进程的ID,结束进程的函数

 

BOOL KillProcessById(DWORD pID) 

       HANDLE Hwnd; 
       bool ret = FALSE; 
       Hwnd = OpenProcess(PROCESS_TERMINATE | SYNCHRONIZE,0,pID); 
       if (Hwnd) 
       { 
              if (TerminateProcess(Hwnd, 0)) 
              { 
                     ret = true
              } 
       } 
       return ret; 

关于结束进程的方法也有其他的一些方法。

1. 上面所说的直接TerminateProcess()

这个方法比较野蛮。但是比较好用。TerminateProcess返回的时候进程已经结束。

2. 发送消息给目标窗口。

直接给目标窗口发送WM_CLOSE,有的程序会修改此消息,变成程序最小化(QQ)。不行就发送WM_QUIT,这个一般都管用的。

BOOL PostMessage(      

    HWND hWnd,

    UINT Msg,

    WPARAM wParam,

    LPARAM lParam

);

这里面有个难点就是,怎么知道目标窗口的hwnd,如果有VC的话,可以用自带的工具SPY++来获得窗口的hwnd,注意程序每次启动后的主窗口hwnd是不是一样的。

由于,发消息成功,并不代表程序也已经结束,所以如果想等目标进程(B)结束后,再继续运行源程序的话(A),要利用以下的方式WaitForSingleObject,参数是进程的handle,通过进程的ID得到。

DWORD WaitForSingleObject(

  HANDLE hHandle,

  DWORD dwMilliseconds

);

而,通过hwnd可以得到进程ID,方法如下。

DWORD GetWindowThreadProcessId(      

    HWND hWnd,

    LPDWORD lpdwProcessId

);

参考code如下:

DWORD pID;

//根据hwnd得到进程的ID,pid

GetWindowThreadProcessId(hwnd, &pID)

//得到进程的handle。

HANDLE hp =OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE,FALSE,pid);

//等待直到进程结束。进程结束会发出信号出来。并且 WaitForSingleObject返回WAIT_OBJECT_0。

WaitForSingleObject(hp, INFINITE);

补充一个由进程Id得到窗口ID的方法,由于从网上找到的,没有实验。

进程启动完毕,然后调用函数EnumWindows(EnumWindowsProc,0)  

//EnumWindowsProc是回调函数  

回调函数EnumWindowsProc为:  

 

BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lparam) 

CString strPrompt; 
DWORD ProcId; 
DWORD ThreadId; 
ThreadId=GetWindowThreadProcessId(hwnd,&ProcId) 
if(ProcId==ProcessInfo.dwProcessId) 

HWND targetWin; 
targetWin=hwnd; 
while(true

HWND hTemp; 
hTemp=GetParent(targetWin); 
if(hTemp==NULL) break
else targetWin=hTemp; 

 
char szTemp[255]; 
sprintf(szTemp,"%x",ProcId); 
CString strTemp=szTemp; 
GetWindowText(targetWin,strTemp.GetBuffer(255),255); 
return FALSE; 

else 
return true
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: