本文要實現的功能就是在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
long __stdcall callback(EXCEPTION_POINTERS *excp)
{
return EXCEPTION_EXECUTE_HANDLER;
}
int main()
{
SetUnhandledExceptionFilter(callback);
//只是爲了讓程序崩潰
_asm int 3;
return 0;
}
如何獲取進程ID呢?
由於在這裏我是用一個程序來監視另外一個exe程序的,因此我能夠經過exe程序的名字來獲取這個進程的進程ID,方法以下,GetProcessIdFromName函數輸入的就是exe程序的名字,例如"test.exe"。
DWORD GetProcessIdFromName(const char*processName)
{
PROCESSENTRY32 pe;
DWORD id = 0;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
pe.dwSize = sizeof(PROCESSENTRY32);
if( !Process32First(hSnapshot,&pe) )
return 0;
char pname[300];
do
{
pe.dwSize = sizeof(PROCESSENTRY32);
if( Process32Next(hSnapshot,&pe)==FALSE )
break;
//把WCHAR*類型轉換爲const char*類型
sprintf(pname,"%ws",pe.szExeFile);
//比較兩個字符串,若是找到了要找的進程
if(strcmp(pname,processName) == 0)
{
id = pe.th32ProcessID;
break;
}
} while(1);
CloseHandle(hSnapshot);
return id;
}
若是這個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,)
HWND m_handle = 0;
int num = 0;
while(m_handle == 0 && num < 60){
m_handle = ::FindWindowA(NULL, "untitled1");
++num;
Sleep(100);
}
if(m_handle != 0)
{
::SendMessageA(m_handle,WM_CLOSE,0,0);
}