本文要实现的功能就是在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);
}