下面我先从此工程的作用讲起:

此工程适用于程序异常退出,然后自动重启该程序。对于,系统重启不了该进程,那此程序将返回-1,也无法进行下一步工作。

下面,先从配置开始讲起:

参考资料:http://hi.baidu.com/hustor/item/ba85ffba3b84d7ee4fc7fdc0

windows下ACE怎样安装与使用说明    (已经很详细)

但是,为节省大家时间,我已经完成部分工作,大家只需要引用若干文件即可。(光编译估计就需要花费 40min,还得视电脑配置),整个文件大概在1.9G左右。

具体步骤如下:

1、请大家到此网站下载压缩包:ACE_wrappers.zip(已经编译完毕),解压到一个合适的位置。

http://pan.baidu.com/s/1o66wdSY

2、配置环境变量

这一步主要是为了大家跨平台使用而设的。

点击计算机 --- 属性 --- 高级系统设置

在”系统变量”中新建变量名 ACE_ROOT, 变量值为 你刚刚解压文件的存放位置比如我的是 D:\Process Monitor\ACE_wrappers

并在 “用户变量”下 新建变量 Path ,值设为 %ACE_ROOT%\lib, 当然,你也可以设为绝对路径,D:\Process Monitor\ACE_wrappers\lib 都是可以的。

这样做的目的是为了,当我们引用动态链接库的时候,VS中就可以不用管了,不然,我们还需要在VS中手动添加.dll,这个也很麻烦。

这两部完成之后,点击确定即可。

3、测试配置环境

从刚刚解压的文件中,D:\Process Monitor\ACE_wrappers\examples (这是我的文件目录)下面,随便拷贝一个工程下来,这里用Logger举例。

拷贝Logger文件夹到其他位置,然后打开工程 Logger_vc10.sln (这里我用的是VS2010),如果大家用的是VS2012请打开Logger_vc11.sln。打开之后,会出现一个解决方案,三个项目。

第一次编译,肯定会不成功。因为我们还没加入.h 和 .lib 文件。即:头文件和库文件

选中某一个项目,右击 ---- 属性 ---- VC++ 目录,在”包含目录“中写上   D:\Process Monitor\ACE_wrappers

在”库目录“中,写上  D:\Process Monitor\ACE_wrappers\lib   。在这里面写有一个好处就是,你下次在重新建立项目的时候,就不用在配置了,配置一次,一劳永逸。它属于全局配置,当然,我们也可以为单个项目进行配置。

如下图所示:

当对单个项目进行配置的时候,需要在 C/C++和链接器中进行配置。这里暂不配置。

此时再编译就OK了。(需要对三个项目分别作上述配置)

4、下面进入正题,使用ACE实现进程监控

参考资料: http://blog.csdn.net/dgyanyong/article/details/12156977/    使用ACE监控启动进程,进程崩溃后自动重启(windows/linux通用)

整个项目的大致如下面的框架结构:

我是用的Logger项目,将底下的其他项目剔除掉,然后新建自己的类。

//使用ACE监控启动进程,进程崩溃后自动重启(windows/linux通用)

原理:

监护程序使用子进程的方式启动各个进程,

子进程退出时,监护程序能够得到相应的退出信号,

从而在子进程退出后,在重新启动相应的子进程。

//----------------------------------------------------------
//配置文件ProcessManager.conf格式
//./PROCESS_MANAGER 1
//./PROCESS_MANAGER 2
//----------------------------------------------------------

类似:举例如下

D:\OpenCV_demo\Debug\OpenCV_02  1
D:\OpenCV_demoMultiReadData\Debug\OpenCV_02  2

.h 文件如下:

//CProcessManager.h
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <string>
#include <map>
 
#include "ace/OS.h"
#include "ace/streams.h"
#include "ace/Log_Msg.h"
#include "ace/Date_Time.h"
#include "ace/Event_Handler.h"
#include "ace/Reactor.h"
#include "ace/Process_Manager.h"
 
using namespace std;
 
// 进程监控,进程崩溃后,自动重新启动进程
class CProcessManager
{
public:
    CProcessManager(){};
    virtual ~CProcessManager(){};
    // 从配置文件读取进程列表信息
    virtual int ReadConfigProcessInfo(char *pFileName);
    // 启动进程,并进行进程监控,进程崩溃后,自动重新启动进程
    virtual int ProcessMonitor();
 
private:
    vector<string> m_vConfigProcessInfo;       // 进程列表信息
};
 
// 回调事件,程序退出后,执行handle_exit函数
class CProcessExitHandler: public ACE_Event_Handler
{
public:
    CProcessExitHandler(){};
    virtual ~CProcessExitHandler(){};
    // 程序退出后,执行该函数
    virtual int handle_exit(ACE_Process* process);
};

.cpp文件

//CProcessManager.cpp
 
 
#include "CProcessManager.h"
 
ACE_Process_Manager *g_pPM;             // 进程管理
map<string, pid_t> g_mapProcessInfo;    // 进程ID管理列表
 
// 读取进程列表配置文件
int CProcessManager::ReadConfigProcessInfo(char *pFileName)
{
    char *pTemp = NULL;
    char szTemp[1024];
    string strTemp = "";
    if(NULL == pFileName) 
    {
        ACE_DEBUG((LM_ERROR, ACE_TEXT("[%N:%l]: Parameter FileName is null.\n")));
        return -1;
    }
    // 文件格式
    //./PROCESS_MANAGER 1
    //./PROCESS_MANAGER 2
    // 打开进程列表配置文件
    FILE *fp = fopen(pFileName, "r");
    if(NULL == fp)
    {
        ACE_DEBUG((LM_ERROR, ACE_TEXT("[%N:%l]: file open error.[%s]\n"), pFileName));
        return -2;
    }
    // 循环读取进程列表配置文件
    while(1)
    {
        memset(szTemp, 0, sizeof(szTemp));
        pTemp = fgets(szTemp, sizeof(szTemp), fp);
        if(NULL == pTemp)
        {
            break;
        }
        // 去掉注释
        if(szTemp[0] == '#')
        {
            continue;
        }
        strTemp = szTemp;
        if(strTemp.length() == 0)
        {
            continue;
        }
        // 去掉回车换行
        if(strTemp[strTemp.length() - 1] == '\n')
        {
            strTemp[strTemp.length() - 1] = 0;
        }
        if(strTemp.length() == 0)
        {
            continue;
        }
        if(strTemp[strTemp.length() - 1] == '\r')
        {
            strTemp[strTemp.length() - 1] = 0;
        }
        if(strTemp.length() == 0)
        {
            continue;
        }
        // 把读取的进程信息放到[进程列表信息]全局变量
        m_vConfigProcessInfo.push_back(strTemp);
    }
    // 关闭进程列表配置文件
    fclose(fp);
    // [进程列表信息]不应该为0
    if(m_vConfigProcessInfo.size() == 0)
    {
        ACE_DEBUG((LM_ERROR, ACE_TEXT("[%N:%l]: Process list is null.[%s]\n"), pFileName));
        return -3;
    }
    return 0;
}
 
// 进程监控   成功返回0,不成功返回-1.
// 根据配置文件启动进程,并注册进程.退出时,回调函数  
int CProcessManager::ProcessMonitor()
{
    int nRet = 0;
    vector<string>::iterator itrConfig;
    string strStartProcess;
 
    m_vConfigProcessInfo.clear();
 
    // 读取进程列表配置文件
    nRet = ReadConfigProcessInfo("ProcessManager.conf");
    if(nRet != 0)
    {
        ACE_DEBUG((LM_ERROR, 
            ACE_TEXT("[%N:%l]: ReadConfigProcessInfo[%s] error.\n"), "ProcessManager.conf"));
        return -1;
    }
    //实例化拥有100个进程空间的进程管理员(进程管理员为全局变量)
    // Instantiate a process manager with space for 100 processes.
    g_pPM = new ACE_Process_Manager(ACE_Process_Manager::DEFAULT_SIZE, ACE_Reactor::instance());
    CProcessExitHandler procExitHandler;
    // 循环配置进程列表,启动进程
    for(itrConfig = m_vConfigProcessInfo.begin(); itrConfig != m_vConfigProcessInfo.end(); ++itrConfig)
    {
        strStartProcess = *itrConfig;
        // 启动进程
        ACE_Process_Options options;
        options.command_line(strStartProcess.c_str());
        pid_t pid = g_pPM->spawn(options); //创建进程并启动
        // 启动进程失败
        if (pid == ACE_INVALID_PID)
        {
            ACE_DEBUG((LM_ERROR, 
                ACE_TEXT("[%N:%l]: start a child process fail(%d)%s\n"), 
                pid, strStartProcess.c_str()));
            return -1;
        }
        ACE_DEBUG((LM_INFO, 
            ACE_TEXT("[%N:%l]: start a child process success(%d)%s\n"), 
            pid, strStartProcess.c_str()));
        // 注册回调(进程退出时,调用该回调) 一直在进行,算是验证吧
        g_pPM->register_handler(&procExitHandler, pid); //有返回值
        // 添加启动成功的进程到进程ID管理列表(哈希结构,键值图,string-int结构)
        g_mapProcessInfo[strStartProcess] = pid;
        ACE_OS::sleep(1);
    }
    //运行反应器模式,一直循环等待事件发生,这个事件就是进程退出的事件,下面的方法一直在等待子进程退出,一退出则执行handle_exit方法。
    // Run the reactor event loop waiting for events to occur.
    ACE_Reactor::instance()->run_reactor_event_loop();//死循环,直到返回-1为止 循环调用它procExitHandler类的方法handle_exit
    //ACE_Reactor::instance()->end_reactor_event_loop();
    return 0;
}
 
// 进程退出回调函数,使用的时候,我们只需要注册即可。这个属于函数的覆盖
// 程序退出后,执行该函数,重新启动进程
int CProcessExitHandler::handle_exit(ACE_Process* process)
{
    map<string, pid_t>::iterator itrProcess;
 
    ACE_DEBUG((LM_INFO,
        ACE_TEXT("[%N:%l]: Process %d exited with exit code %d\n"),
        process->getpid (), process->return_value()));
 
    // 循环进程ID管理列表,根据进程ID找到退出的进程,重新启动进程
    for(itrProcess = g_mapProcessInfo.begin(); itrProcess != g_mapProcessInfo.end(); ++itrProcess)
    {
        // 根据进程ID,查找进程名
        if(itrProcess->second == process->getpid()) //second指示进程的id号
        {
            // 重新启动进程
            ACE_Process_Options options;
            options.command_line(itrProcess->first.c_str());
            pid_t pid = g_pPM->spawn(options);
            // 重新启动进程失败
            if (pid == ACE_INVALID_PID)
            {
                ACE_DEBUG((LM_ERROR, 
                    ACE_TEXT("[%N:%l]: restart a child process fail(%d)%s\n"), 
                    pid, itrProcess->first.c_str()));
                return -1;
            }
            ACE_DEBUG((LM_INFO, 
                ACE_TEXT("[%N:%l]: restart a child process success(%d)%s\n"), 
                pid, itrProcess->first.c_str()));
            // 注册回调(进程退出时,调用该回调)
            g_pPM->register_handler(this, pid); //验证(感觉像是递归,只有成功后才返回,保证程序执行)
            // 添加启动成功的进程到进程ID管理列表
            itrProcess->second = pid;
            break;
        }
    }
    return 0;
}

主文件 main()

 
 
// main.cpp
#include "CProcessManager.h"
 
int main(int argc, ACE_TCHAR *argv[])
{
  // Running as a child for test.
    if (argc > 1)
    {
        ACE_OS::sleep(10);
        return 0;
    }
    // set output log file
    ACE_OS::setprogname("ProcessManagerLog");
    ACE_Date_Time tvTime(ACE_OS::gettimeofday());
    char szLogFileName[256];
    memset(szLogFileName, 0, sizeof(szLogFileName));
    sprintf(szLogFileName, "log/%s_%04d%02d%02d_%02d%02d%02d.log", 
        ACE_OS::getprogname(), 
        (int)tvTime.year(), (int)tvTime.month(),  (int)tvTime.day(), 
        (int)tvTime.hour(), (int)tvTime.minute(), (int)tvTime.second());
 
    ACE_OSTREAM_TYPE *pLogOutput = new ofstream(szLogFileName);
    ACE_LOG_MSG->msg_ostream(pLogOutput, true);
    ACE_LOG_MSG->set_flags(ACE_Log_Msg::OSTREAM);
    // Prepends timestamp and message priority to each message
    ACE_LOG_MSG->set_flags(ACE_Log_Msg::VERBOSE_LITE);
    //ACE_LOG_MSG->clr_flags(ACE_Log_Msg::STDERR);
 
    ACE_DEBUG((LM_INFO, ACE_TEXT("[%N:%l]: ---ProcessManager START---.\n")));
    int nRet = 0;
    CProcessManager *pProcMng = new CProcessManager();
    // 启动进程监控
    nRet = pProcMng->ProcessMonitor();
    if(nRet != 0)
    {
        ACE_DEBUG((LM_ERROR, ACE_TEXT("[%N:%l]: ---ProcessMonitor Error---\n")));
    }
    delete pProcMng;
    ACE_DEBUG((LM_INFO, ACE_TEXT("[%N:%l]: ---ProcessManager STOP---.\n")));
    ACE_LOG_MSG->clr_flags(ACE_Log_Msg::OSTREAM);
    delete pLogOutput;
    return 0;
}
 
 
 

其他内容介绍:

C++ 网络编程库套件
Adaptive Communication Environment(自适配通信环境),简称ACE。为一个以C++的

Template技术所做成的开放源代码的可跨平台的网络应用程序的程序库套件。它提供了

socket/threading/memory management等多种系统调用的面对对象的wrapper,使C++通信软件

开发更加简单。

官方网站

The ADAPTIVE Communication Environment (ACE)

相关书籍

The ACE Programmer's Guide,ISBN 0-201-69971-0

C++ Network Programming

Mastering Complexity Using ACE and Patterns,ISBN 0-201-60464-7

Systematic Reuse with ACE and Frameworks,ISBN 0-201-79525-6

《C++ Network Programming》就是ACE项目的负责人Schmidt写的,这位老哥以前是华盛

顿大学的副教授,主要研究领域是软件工程(他写了不少关于pattern的文章和书),现在猫到

UC Irvine去了。这两本书主要介绍了ACE的使用,也涉及了部份设计方面的内容。第一卷主要

介绍ACE的基本功能和使用,第二卷则偏重通讯软件中的design pattern。搞通信软件开发的

兄弟们绝对应该看看此书。另外也有人推荐把ACE作为学习C++的范例来学习,呵呵,这就是个

人喜好的问题了...总的来说ACE的代码风格还是很不错的--比STL那些天书好看些。

ACE下载地址:http://download.dre.vanderbilt.edu/

关于ACE的资料下载:http://download.csdn.net/search?q=adaptive%20communication

%20environment

一篇好的帖子:http://blog.csdn.net/dgyanyong/article/details/12156977/

使用ACE监控启动进程,进程崩溃后自动重启(windows/linux通用)

http://daimojingdeyu.iteye.com/blog/828696  Reactor模式的理解

http://blog.csdn.net/chexlong/article/details/5886700   Windows 平台上安装测试ACE

记录

http://blog.csdn.net/zyysql/article/details/6637920 ace第一课--windows下装ace

http://hi.baidu.com/hustor/item/ba85ffba3b84d7ee4fc7fdc0   windows下ACE怎样安装与

使用说明?

http://blog.csdn.net/chexlong/article/details/5886700           Windows 平台上安装测试ACE记录

http://www.kuqin.com/ace-2002-12/Part-Two/Chapter-4.htm      ACE线程管理

资料下载: http://download.csdn.net/search?q=adaptive%20communication%20environment

ACE实现日志记录:  ACE_Log_Msg 类的使用

http://blog.csdn.net/cskerrydn/article/details/4645219

http://bdxnote.blog.163.com/blog/static/8444235200882053248733/             ACE_Log_Msg日志格式

这里介绍一个小知识点:如何将文件保存到指定目录   http://zhidao.baidu.com/link?url=wzcs4KtlJRnyU4QrUusDF6SFqs2G4x6JoDDhwbdtiIBC1b4jdEHDV3eMhTDaUDJ5STbwHM4veaOVSbyApXz4yK

    sprintf(szLogFileName, "D:\\Process Monitor\\Logger\\Acceptor-server\\log\\%s_%04d%02d%02d_%02d%02d%02d.log", 
        ACE_OS::getprogname(), 
        (int)tvTime.year(), (int)tvTime.month(),  (int)tvTime.day(), 
        (int)tvTime.hour(), (int)tvTime.minute(), (int)tvTime.second());

对于上面的函数,\\   第一个\为转义字符。然后,假如想指定到某一个目录下,必须要先建立好文件夹,默认不会建立文件夹的。而且,你假如不指定,会直接放在此项目的目录下。

//补充两篇好帖子:

http://blog.csdn.net/someyuan/article/details/3855491                 ACE_REACTOR框架处理事件              很好的阐释了Rector框架的精髓

http://bdxnote.blog.163.com/blog/static/8444235200810575055324/           ACE进程Wrapper---ACE_Process用法

整个项目的下载地址:  http://pan.baidu.com/s/15yDWy

注:1)配置文件不支持中文目录。  2)支持C++/C#

举例如下:

存在的问题:

1、无法解决程序卡死的问题,程序卡死对此监控程序来说,进程还是处于运行状态,状态码是正确的。只能解决某个进程突然退出的情况。

2、监控程序可能比较难以关闭,我们可以通过热启动键打开任务管理器关闭。当然,通过程序自身的关闭按钮也可以。

3、此程序运行在一台工控机上。对于多机通讯问题,没有做。

此程序的实现原理:其实很简单,就是监控程序作为一个父进程,然后其他进程都是子进程,都是从监控这个进程里面开辟的子进程,当然,这些都是别人帮你弄好了,只要会用即可。

如果有问题,大家可以留言,相互交流。此程序也是参考别人的,不是本人写的,如有不对的地方请批评指正。

下面补充一点知识:

几个函数的使用:

前天打算开辟一个线程去监视各个子进程的状态,如果进程没反应或者死掉,我们可以通过返回给我们的状态码去判断程序是否死掉。如果死掉了,就去触发另一个线程(用事件去做),让它先关闭进程然后隔个1000ms在打开此进程。

结果,查了老半天,获得了解决的办法。主要是两个函数的使用: IsHungAppWindow((HWD)hProcess)  和  sendmessagetimeout().

参考文章:

http://wenku.baidu.com/link?url=90tVZzjf_5xkYHc6u32w6TYiM9XJKqP2vUTUZpDkgxNWZSiWCq_eh3E6sLuOSA07tzFKgE6f5b5DJySVuMcIlFWJnW6NgtnE8Pn-ogOopZa

进程句柄的获取

//利用进程ID打开该进程,并获取进程句柄

HANDLE hProcess = OpenProcess(PROCESS_TERMINATE,FALSE,itrProcess->second);

bool Isgone = TRUE;

Isgone = IsHungAppWindow((HWND)hProcess); //当句柄无效或句柄所标识的窗体的消息循环是正常的,则返回0,否则返回1,代表挂了

http://msdn.microsoft.com/zh-cn/vstudio/ms633526(v=vs.80).aspx     IsHungAppWindow function use
http://bbs.csdn.net/topics/360168583                                               用windows API怎样去监测一个程序是否运行?                                      http://www.cnblogs.com/Joseph/articles/1940149.html                        怎么样判断一个进程出错或未响应

http://bbs.csdn.net/topics/90969                                            如何在程序中判断系统中有进程已经停止响应了

两种使用方法程序如下: (不过,遗憾的是,两种调试都没成功。)

DWORD WINAPI ChildFunc(LPVOID p)
{
HANDLE hEvent = CreateEventW(NULL,FALSE,FALSE,(LPCWSTR)("ChildEvent"));
memset(processName,,sizeof(processName));
InitializeCriticalSection(&g_csTreadCode);
bool bDone = true;
while(bDone)
{
DWORD dwStatus = WaitForSingleObject(hEvent,INFINITE);
if (dwStatus == WAIT_OBJECT_0)
{
EnterCriticalSection(&g_csTreadCode); string proName = "";
int proId = ;
if (recvcount == )
{
proName = processName[];
proId = processId[];
}
else
{
proName = processName[recvcount - ];
proId = processId[recvcount - ];
}
//先关闭进程,然后重启进程 g_pPM ->terminate(proId); // 重新启动进程
ACE_Process_Options options;
options.command_line(proName.c_str());
pid_t pid = g_pPM->spawn(options);
// 重新启动进程失败
if (pid == ACE_INVALID_PID)
{
return -;
}
//重启之后,进程表ID是会变的,这时需要更新进程列表 g_mapProcessInfo[proName] = pid;
LeaveCriticalSection(&g_csTreadCode);
}
}
return ;
} //DWORD WINAPI ChildFunc1(LPVOID p)
//{
// HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS,FALSE,(LPCTSTR)("ChildEvent"));
//
// bool bDone = true;
// while(bDone)
// {
// map<string, pid_t>::iterator itrProcess;
//
// // 循环进程ID管理列表,根据进程ID找到退出的进程,重新启动进程
// for(itrProcess = g_mapProcessInfo.begin(); itrProcess != g_mapProcessInfo.end(); ++itrProcess)
// {
// //利用进程ID打开该进程,并获取进程句柄
// HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,itrProcess->second);
//
// //bool Isgone = TRUE;
//
// //Isgone = IsHungAppWindow((HWND)hProcess); //当句柄无效或句柄所标识的窗体的消息循环是正常的,则返回0,否则返回1,代表挂了
//
// //g_pPM ->terminate(itrProcess->second);
// DWORD_PTR dwResult = 0;
// LRESULT lr = ::SendMessageTimeout((HWND)hProcess,WM_NULL,0,0,SMTO_ABORTIFHUNG | SMTO_BLOCK,500,&dwResult);//超时0.5s
//
// if (lr)
// {
// //还可以响应
// }
// else
// {
// processName[recvcount] = itrProcess ->first;
// processId[recvcount] = itrProcess ->second;
// recvcount++;
//
// if (recvcount == 10)
// {
// recvcount = 0;
// }
// SetEvent(hEvent);
// }
//
// }
// }
// return 0;
//}

补充:

通过别人的指点,demo2,终于可以解决进程死掉,然后重启。

代码如下:

// main.cpp
#include "CProcessManager.h" int main(int argc, ACE_TCHAR *argv[])
{
// Running as a child for test.
if (argc > )
{
ACE_OS::sleep();
return ;
}
// set output log file
ACE_OS::setprogname("ProcessManagerLog");
ACE_Date_Time tvTime(ACE_OS::gettimeofday());
char szLogFileName[];
memset(szLogFileName, , sizeof(szLogFileName));
sprintf(szLogFileName, "D:\\Process Monitor\\Logger\\Acceptor-server\\log\\%s_%04d%02d%02d_%02d%02d%02d.log",
ACE_OS::getprogname(),
(int)tvTime.year(), (int)tvTime.month(), (int)tvTime.day(),
(int)tvTime.hour(), (int)tvTime.minute(), (int)tvTime.second()); ACE_OSTREAM_TYPE *pLogOutput = new ofstream(szLogFileName); //如何让文件输出到指定的文件下
ACE_LOG_MSG->msg_ostream(pLogOutput, true);
ACE_LOG_MSG->set_flags(ACE_Log_Msg::OSTREAM);//ostream 设置log的输出目的地或格式
// Prepends timestamp and message priority to each message
ACE_LOG_MSG->set_flags(ACE_Log_Msg::VERBOSE_LITE);//verbose_lite
//ACE_LOG_MSG->clr_flags(ACE_Log_Msg::STDERR); ACE_DEBUG((LM_INFO, ACE_TEXT("[%N:%l]: ---ProcessManager START---.\n")));
int nRet = ;
CProcessManager *pProcMng = new CProcessManager();
// 启动进程监控
HANDLE hChild = CreateThread(NULL,,ChildFunc,,,NULL);
HANDLE hChild1 = CreateThread(NULL,,ChildFunc1,,,NULL); nRet = pProcMng->ProcessMonitor();//死循环,执行不到下面 if(nRet != )
{
ACE_DEBUG((LM_ERROR, ACE_TEXT("[%N:%l]: ---ProcessMonitor Error---\n")));
}
delete pProcMng;
ACE_DEBUG((LM_INFO, ACE_TEXT("[%N:%l]: ---ProcessManager STOP---.\n")));
ACE_LOG_MSG->clr_flags(ACE_Log_Msg::OSTREAM); //取消log的输出目的地或格式
delete pLogOutput;
return ;
} DWORD WINAPI ChildFunc(LPVOID p)
{
HANDLE hEvent = CreateEvent(NULL,FALSE,FALSE,"ChildEvent");
memset(processName,,sizeof(processName));
InitializeCriticalSection(&g_csTreadCode);
bool bDone = true;
while(bDone)
{
DWORD dwStatus = WaitForSingleObject(hEvent,INFINITE);
if (dwStatus == WAIT_OBJECT_0)
{
EnterCriticalSection(&g_csTreadCode); string proName = "";
int proId = ;
if (recvcount == )
{
proName = processName[];
proId = processId[];
}
else
{
proName = processName[recvcount - ];
proId = processId[recvcount - ];
}
//先关闭进程,然后重启进程 g_pPM ->terminate(proId); // 重新启动进程 注:在程序开始的时候,死掉的进程已经加入到进程列表,所以这里不用在重启进程,另一个线程里面会帮我们重启
//ACE_Process_Options options;
//options.command_line(proName.c_str());
//pid_t pid = g_pPM->spawn(options);
//// 重新启动进程失败
//if (pid == ACE_INVALID_PID)
//{
// return -1;
//}
////重启之后,进程表ID是会变的,这时需要更新进程列表
//g_mapProcessInfo[proName] = pid;
LeaveCriticalSection(&g_csTreadCode);
}
}
return ;
} DWORD WINAPI ChildFunc1(LPVOID p)
{
Sleep();//50ms 检测一次
bool bDone = true;
HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS,FALSE,"ChildEvent");//不要用强制转换,行不通
while(bDone)
{
map<string, pid_t>::iterator itrProcess;
// 循环进程ID管理列表,根据进程ID找到退出的进程,重新启动进程
for(itrProcess = g_mapProcessInfo.begin(); itrProcess != g_mapProcessInfo.end(); ++itrProcess)
{
//利用进程ID打开该进程,并获取进程句柄 (一个进程它还有窗口句柄(子句柄),这两者不一样)
//HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,itrProcess->second); //先解析得到窗体名
string str = "";
for (int i = itrProcess->first.size()-; i > ; --i)
{
char c = itrProcess->first[i];
if (c == ' ' || (c >= '' && c <= ''))
{
continue;
}
if (c != '\\' )
{
str += c;
}
if (c == '\\')
{
break;
}
}
string s(str.rbegin(),str.rend());//反转
HWND hProcess = FindWindow(NULL,s.c_str()); //cout << s << endl;
bool Isgone = TRUE; Isgone = IsHungAppWindow(hProcess); //当句柄无效或句柄所标识的窗体的消息循环是正常的,则返回0,否则返回1,代表挂了 if (Isgone)
{
processName[recvcount] = itrProcess ->first;
processId[recvcount] = itrProcess ->second;
recvcount++; if (recvcount == )
{
recvcount = ;
}
SetEvent(hEvent);
}
}
}
return ;
} //DWORD WINAPI ChildFunc1(LPVOID p)
//{
// bool bDone = true;
// while(bDone)
// {
// map<string, pid_t>::iterator itrProcess;
//
// // 循环进程ID管理列表,根据进程ID找到退出的进程,重新启动进程
// for(itrProcess = g_mapProcessInfo.begin(); itrProcess != g_mapProcessInfo.end(); ++itrProcess)
// {
// //利用进程ID打开该进程,并获取进程句柄
// HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,itrProcess->second);
// DWORD_PTR dwResult = 0;
// LRESULT lr = ::SendMessageTimeout((HWND)hProcess,WM_NULL,0,0,SMTO_ABORTIFHUNG | SMTO_BLOCK,1000,&dwResult);//超时0.5s
//
// if (lr)
// {
// //还可以响应
// }
// else
// {
// InitializeCriticalSection(&g_csTreadCode);
// EnterCriticalSection(&g_csTreadCode);
//
// //先关闭进程,然后重启进程
// g_pPM ->terminate(itrProcess->second);
//
// // 重新启动进程
// ACE_Process_Options options;
// options.command_line(itrProcess->first.c_str());
// pid_t pid = g_pPM->spawn(options);
// // 重新启动进程失败
// if (pid == ACE_INVALID_PID)
// {
// return -1;
// }
// //重启之后,进程表ID是会变的,这时需要更新进程列表
// g_mapProcessInfo[itrProcess->first] = pid;
// LeaveCriticalSection(&g_csTreadCode);
// }
//
// }
// }
// return 0;
//}

参考文档:

http://blog.csdn.net/ddkxddkx/article/details/6332268     c++ string 实现逆序

http://blog.csdn.net/coolszy/article/details/5523486    FindWindow用法

http://www.cnblogs.com/del/archive/2008/02/28/1085432.html

WinAPI: FindWindow、FindWindowEx - 查找窗口

进程监控模块配置与使用 ------ACE(开源项目)的更多相关文章

  1. 配置开源项目 SlidingMenu 的问题

    最近想研究一下开源项目 SlidingMenu,单是配置项目就花了好长的时间,断断续续的尝试,终于配置成功了,写下来和大家分享一下经验. Step 1:导入依赖的项目和例子 打开项目 File -&g ...

  2. 开源项目-SlideMenu和actionbarsherlock的配置

    SlidingMenu 是github上一个非常优秀的开源库,利用它可以很方便的实现左右侧滑菜单的效果,现在这个基本上应用的标配了,如果一个App没有滑动效果基本上是不可能的,中国人都是本着人无我有, ...

  3. 盘点 Github 所用到的开源项目

    http://www.php100.com/html/it/mobile/2014/0401/6736.html 在致力于开源事业的同时,Github也使用一些非常优秀的开源项目的来打造自己的平台与服 ...

  4. 【分享】2017 开源中国新增开源项目排行榜 TOP 100

    2017 年开源中国社区新增开源项目排行榜 TOP 100 新鲜出炉! 这份榜单根据 2017 年开源中国社区新收录的开源项目的关注度和活跃度整理而来,这份最受关注的 100 款开源项目榜单在一定程度 ...

  5. 阿里开源项目 druid 相关资料汇总

    项目发起人访谈:http://www.iteye.com/magazines/90 github主页:https://github.com/alibaba/druid druid 项目,我想我能用很短 ...

  6. .Net 开源项目资源大全

    伯乐在线已在 GitHub 上发起「DotNet 资源大全中文版」的整理.欢迎扩散.欢迎加入. https://github.com/jobbole/awesome-dotnet-cn (注:下面用 ...

  7. Github上关于iOS的各种开源项目集合(强烈建议大家收藏,查看,总有一款你需要)

    下拉刷新 EGOTableViewPullRefresh - 最早的下拉刷新控件. SVPullToRefresh - 下拉刷新控件. MJRefresh - 仅需一行代码就可以为UITableVie ...

  8. swift开源项目精选

    Swift 开源项目精选-v1.0 2016-03-07 22:11 542人阅读 评论(0) 收藏 举报  分类: iOS(55)   Swift(4)    目录(?)[+]   转自 http: ...

  9. 开源项目大全 >> ...

    http://www.isenhao.com/xueke/jisuanji/kaiyuan.php   监控系统-Nagios 网络流量监测图形分析工具-Cacti 分布式系统监视-zabbix 系统 ...

随机推荐

  1. LeetCode(136) Single Number

    题目 Given an array of integers, every element appears twice except for one. Find that single one. Not ...

  2. LeetCode(7)Reverse Integer

    题目: Reverse digits of an integer. Example1: x = 123, return 321 Example2: x = -123, return -321 分析: ...

  3. cf898d Alarm Clock

    区间上有 \(n\) 个点,问你为达到目的:长度为 \(m\) 的区间内点的个数都 $ < k$需要去掉多少个点. 贪心.每个区间我们总是去掉最后的,也就是说除非万不得已我们是不会去掉点的. 队 ...

  4. xfce-OpenVAS自动化安全风险评估指南

    1.  登录系统 在客户端,打开浏览器,在地址栏输入https://IP:9392/ 看到如下界面: 我们要信任此网站,点击继续浏览此网站,进入系统登录界面,如下图: 输入我提供的通用登录账号:wdl ...

  5. Python内置函数5

    Python内置函数5 1.format参考前面字符串方法中的format 2.frozenset([iterable]) iterable -- 可迭代的对象,比如列表.字典.元组等等 返回一个冻结 ...

  6. APP版本升级

    /*** version_upgrade 版本升级信息表*/CREATE TABLE `version_upgrade` ( `id` smallint(4) unsigned NOT NULL AU ...

  7. Android点击两次返回退出程序

    代码改变世界 Android点击两次返回退出程序 private long mExitTime; public boolean onKeyDown(int keyCode, KeyEvent even ...

  8. 算法复习——莫队算法(bzoj1878)

    题目: Description HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一 段贝壳,思考它们所表达的含义.HH不断地收集新的贝壳,因此他的 ...

  9. 【单调队列+二分查找】bzoj 1012: [JSOI2008]最大数maxnumber

    [题意] 维护一个单调递减的q数组,用id数组记录q数组的每个下标对应在原数组的位置,那么id数组一定有单调性(q数组中越靠后,原数组中也靠后),然后二分查找这个数 [AC] #include< ...

  10. 【2018.10.15】WZJ笔记(数论)

    1. 证明:对于任意质数$p\gt 3$,$p^2-1$能被$24$整除. 证:平方差公式,$p^2-1 = (p-1)(p+1)$. 再把$24$分解质因数$2^3*3$. 三个相邻的自然数中至少有 ...