windows C/C++ 在一個程序中打開,關閉和監視其它的exe程序

本文要實現的功能就是在windows下,實現用一個程序來打開,關閉和監視其它的exe程序,我這裏的的exe程序是我本身實現的。windows

1.監視exe是否崩潰函數

首先若是一個進程不在了,它的進程ID就是0, 那麼經過檢測進程ID是否爲0,就能夠知道進程是否還在運行。code

假設程序崩潰了,它的進程ID會變成0,那麼經過檢測進程ID是否爲0,就能夠知道程序是否崩潰。blog

可是在windows下,狀況並非假設的那樣,程序崩潰了,它就彈出一個錯誤對話框,以下圖所示,而且若是不關掉掉這個框,程序就永遠死在這個窗口上,不會退出,進程ID也不會變成0,那麼就不能經過檢測進程ID來判斷程序是否崩潰。因此如今必須讓程序崩潰後直接退出而不是死在錯誤窗口上。
 token

 

解決辦法就是SetUnhandledExceptionFilter函數,使用這個函數就可讓程序崩潰後直接退出,而不是死在錯誤窗口上。這個函數的返回值有三種狀況:接口

EXCEPTION_EXECUTE_HANDLER     表示下面執行__except塊內及其後面的代碼進程

EXCEPTION_CONTINUE_SEARCH     表示回到拋出異常處繼續向下執行字符串

EXCEPTION_CONTINUE_EXECUTION    表示查找下一個異常處理例程入口it

 

SetUnhandledExceptionFilter函數用法示例:io

 

 
  1. long __stdcall callback(EXCEPTION_POINTERS *excp)

  2. {

  3. return EXCEPTION_EXECUTE_HANDLER;

  4. }

  5.  
  6. int main()

  7. {

  8. SetUnhandledExceptionFilter(callback);

  9. //只是爲了讓程序崩潰

  10. _asm int 3;

  11. return 0;

  12. }

 

如何獲取進程ID呢?

由於在這裏我是用一個程序來監視另外一個exe程序的,因此我能夠經過exe程序的名字來獲取這個進程的進程ID,方法以下,GetProcessIdFromName函數輸入的就是exe程序的名字,例如"test.exe"。

 

 
  1. DWORD GetProcessIdFromName(const char*processName)

  2. {

  3. PROCESSENTRY32 pe;

  4. DWORD id = 0;

  5.  
  6. HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);

  7. pe.dwSize = sizeof(PROCESSENTRY32);

  8. if( !Process32First(hSnapshot,&pe) )

  9. return 0;

  10. char pname[300];

  11. do

  12. {

  13. pe.dwSize = sizeof(PROCESSENTRY32);

  14. if( Process32Next(hSnapshot,&pe)==FALSE )

  15. break;

  16. //把WCHAR*類型轉換爲const char*類型

  17. sprintf(pname,"%ws",pe.szExeFile);

  18. //比較兩個字符串,若是找到了要找的進程

  19. if(strcmp(pname,processName) == 0)

  20. {

  21. id = pe.th32ProcessID;

  22. break;

  23. }

  24.  
  25. } while(1);

  26.  
  27. CloseHandle(hSnapshot);

  28.  
  29. return id;

  30. }

 

若是這個exe程序崩潰了,如何從新打開exe呢?

這裏我採用最簡單的WinExec()函數:

WinExec("C:\\exams\\test.exe",SW_SHOW);


如何主動關閉exe程序呢?

//經過進程名獲取進程ID
DWORD pid = GetProcessIdFromName("test.exe");
//獲取進程的最大權限
HANDLE token = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);
//關閉進程
TerminateProcess(token, 0);


注意啦!!!!!!!!!

在上面獲取進程ID的時候,必定是"test.exe",只是exe程序的名字,沒有路徑!沒有路徑!沒有路徑!重要的事情說三遍!不然獲取不到進程ID。可是WinExec打開的時候就要加上路徑了,固然若是控制程序和exe程序在相同目錄下,就沒必要啦。

我寫的時候是char filename[] = "C:\\exams\\test.exe",而後後面打開和獲取進程ID的時候都用的是filename,致使我在關exe的時候一直關不掉,困擾了我很久。

 我添加的頭文件有:

#include<windows.h>

#include<tlhelp32.h>

#include<comdef.h>

 

關於windows關閉窗口的API

剛開始覺得是 CLoseWindow(句柄);  然而這個接口只是窗口最小化

百度後覺得是 DestroyWindow(句柄) : 而後這接口運行沒有任何效果,不知爲什麼

正確的應該是 ::SendMessage(句柄,WM_CLOSE,0,0,)

 
  1. HWND m_handle = 0;

  2. int num = 0;

  3. while(m_handle == 0 && num < 60){

  4. m_handle = ::FindWindowA(NULL, "untitled1");

  5. ++num;

  6. Sleep(100);

  7. }

  8. if(m_handle != 0)

  9. {

  10. ::SendMessageA(m_handle,WM_CLOSE,0,0);

  11. }

相關文章
相關標籤/搜索