所谓守护进程,顾名思义是通过另一个进程对某个重要的进程进行保护,防止被保护进程异常退出,与看门狗功能类似。编写此类功能,思路非常简单,首先我们需要一个定时任务对所有的进程进行扫描,然后核对需要守护的进程的相关信息如进程名,是否在系统进程列表中,如果不在则表示进程已经退出,需要通过编码方式启动被守护进程。
废话不多说,直接上代码:
首先贴上常用的线程操作工具类
#include <windows.h>
class ThreadUtils
{
public:
/** @struct ThreadUtils::Context<T>
* @brief 线程参数上下文
*/
template<class T>
struct Context
{
T* owner; ///<*线程函数所属类指针
ThreadUtils* caller; ///<*线程函数的调用者
void (T::*ThreadProc)(); ///<*类成员函数
};
template<class T>
static DWORD __stdcall s_Proc(LPVOID param)
{
if (param)
{
Context<T>* pCon = reinterpret_cast<Context<T>*>(param);
T* pType = reinterpret_cast<T*>(pCon->owner);
if (pType)
{
(pType->*(pCon->ThreadProc))();///<*调用类成员函数
}
delete pCon;
}
return 0;;
}
public:
ThreadUtils()
{
m_thread = NULL;
}
~ThreadUtils(void)
{
wait();
}
template<class T>
bool call(T* pClass, void (T::*ThreadProc)())
{
wait();
Context<T>* pcon = new(std::nothrow) Context<T>;
if (NULL == pcon)
{
return false;
}
pcon->owner = pClass;
pcon->ThreadProc = ThreadProc;
pcon->caller = this;
return 0 == CreateThread(NULL, 0, s_Proc<T>, pcon, 0, NULL);
}
void wait()
{
if (m_thread)
{
WaitForSingleObject(m_thread, 5000);
m_thread = NULL;
}
}
private:
HANDLE m_thread;
};
然后看看守护进程的管理类
class CProcessDeamon
{
public:
static CProcessDeamon* Instance()
{
static CProcessDeamon s_psDeamon;
return &s_psDeamon;
}
~CProcessDeamon();
/** @fn bool CProcessDeamon::StartDeamonProcess(const std::string& strProcessName, const std::string& cmdLine)
* @brief 开启进程守护
* @param strProcessName[in] 进程名字,系统进程输入short name即可,如iexplore.exe。
* @param cmdLine[in] 进程所需参数
* @return 成功:true 失败:false
*/
bool StartDeamonProcess(const std::string& strProcessName, const std::string& cmdLine);
/** @fn bool CProcessDeamon::StopDeamonProcess()
* @brief 结束进程守护
* @return
*/
void StopDeamonProcess();
private:
CProcessDeamon();
/// 枚举系统当前所有进程信息
void EnumProcessInfo(std::vector<std::string>& processList);
/// 进程守护
void DeamonProcess();
private:
ThreadUtils m_threadHelper;
HANDLE m_hExitSignal;
std::string m_strProcessName;
std::string m_cmdLine;
};
#include <stdio.h>
#include "DeamonProcess.h"
#include <tlhelp32.h>
#include <algorithm>
#include <ShellAPI.h>
#define MAX_BUF_SIZE 512
bool CProcessDeamon::StartDeamonProcess( const std::string& strProcessName, const std::string& cmdLine )
{
m_strProcessName = strProcessName;
m_cmdLine = cmdLine;
return m_threadHelper.call(this, &CProcessDeamon::DeamonProcess);
}
void CProcessDeamon::StopDeamonProcess()
{
m_strProcessName.clear();
m_cmdLine.clear();
if (NULL != m_hExitSignal)
{
SetEvent(m_hExitSignal);
}
m_threadHelper.wait();
m_hExitSignal = NULL;
}
void CProcessDeamon::EnumProcessInfo( std::vector<std::string>& processList )
{
// 定义进程信息结构
PROCESSENTRY32 pe32 = {sizeof(pe32)} ;
// 创建系统当前进程快照
HANDLE hProcessShot = CreateToolhelp32Snapshot ( TH32CS_SNAPPROCESS, 0 ) ;
if ( hProcessShot == INVALID_HANDLE_VALUE )
return ;
// 循环枚举进程信息
char szBuf[MAX_BUF_SIZE] = {0} ;
if ( Process32First ( hProcessShot, &pe32 ) )
{
do {
processList.push_back(pe32.szExeFile);
}while ( Process32Next ( hProcessShot, &pe32 ) ) ;
}
CloseHandle ( hProcessShot ) ;
}
CProcessDeamon::CProcessDeamon()
{
m_hExitSignal = NULL;
}
CProcessDeamon::~CProcessDeamon()
{
StopDeamonProcess();
}
void CProcessDeamon::DeamonProcess()
{
if (m_strProcessName.empty())
{
return;
}
if (NULL == m_hExitSignal)
{
m_hExitSignal = CreateEvent(NULL, FALSE, FALSE, NULL);
}
while (WAIT_OBJECT_0 != WaitForSingleObject(m_hExitSignal, 10000))
{
std::vector<std::string> plist;
EnumProcessInfo(plist);
if (plist.empty())
{
continue;
}
std::vector<std::string>::iterator it = std::find(plist.begin(), plist.end(), m_strProcessName);
if (it != plist.end())
{
// 进程存在,不处理
continue;
}
// 进程被杀掉,重启一下
ShellExecute(0, "open", m_strProcessName.c_str(), m_cmdLine.c_str(), NULL, SW_SHOW);
//::Sleep(30000);
}
}
最后我们来测试一把:
#include "DeamonProcess.h"
#include <stdio.h>
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
CProcessDeamon::Instance()->StartDeamonProcess("iexplore.exe", "www.baidu.com");
cout<<"开启守护成功"<<endl;
cout<<"回车关闭守护"<<endl;
getchar();
CProcessDeamon::Instance()->StopDeamonProcess();
getchar();
return 0;
}