您的位置:首页 > 运维架构

进程监控模块配置与使用 ------ACE(开源项目)

2014-09-16 17:04 507 查看
下面我先从此工程的作用讲起:

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

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

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

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

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

具体步骤如下:

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

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

2、配置环境变量

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

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

// 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, "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 = 0;
CProcessManager *pProcMng = new CProcessManager();
// 启动进程监控
HANDLE hChild = CreateThread(NULL,0,ChildFunc,0,0,NULL);
HANDLE hChild1 = CreateThread(NULL,0,ChildFunc1,0,0,NULL);

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); //取消log的输出目的地或格式
delete pLogOutput;
return 0;
}

DWORD WINAPI ChildFunc(LPVOID p)
{
HANDLE hEvent = CreateEvent(NULL,FALSE,FALSE,"ChildEvent");
memset(processName,0,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 = 0;
if (recvcount == 0)
{
proName = processName[9];
proId = processId[9];
}
else
{
proName = processName[recvcount - 1];
proId = processId[recvcount - 1];
}
//先关闭进程,然后重启进程

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 0;
}

DWORD WINAPI ChildFunc1(LPVOID p)
{
Sleep(500);//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()-2; i > 0 ; --i)
{
char c = itrProcess->first[i];
if (c == ' ' ||  (c >= '0' && c <= '9'))
{
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 == 10)
{
recvcount = 0;
}
SetEvent(hEvent);
}
}
}
return 0;
}

//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;
//}


View Code

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

/article/1456519.html FindWindow用法

/article/4586635.html

WinAPI: FindWindow、FindWindowEx - 查找窗口

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: