最近开发一个进程监控的服务,由于对windows api不熟,所以折腾了小两周才完全跑通,特记录一下
2 根据进程句柄来获取程序开始运行的时间(多个同名进程里最早的一个)
earliesttime = COleDateTime::GetCurrentTime();
for (i = 0; i < number; i++)
{
GetProcessTimes(hProcess[i], &ftCreation, &ftExit, &ftKernel, &ftUser);
if ((earliesttime - (COleDateTime(ftCreation))).GetTotalSeconds() > 0){
earliesttime = ftCreation;
}
}
3 创建子线程,来监听该程序名的所有进程句柄的结束事件,将结束时间写入redis
for (int j = 0; j < number; j++){
pDataArray[ncount]->hProcess[j] = hProcess[j];
}
pDataArray[ncount]->procname = _strdup(name);
pDataArray[ncount]->num = number;
hThreadArray[ncount] = (HANDLE)_beginthreadex(NULL, 0, &MyThreadFunction, pDataArray[ncount], 0, NULL);
unsigned int _stdcall MyThreadFunction(LPVOID lpParam)
{
char endtime[BUFFERSIZE] = "";
char buffer[BUFFERSIZE] = "";
char buff[BUFFERSIZE] = "";
HANDLE hProcess[20];
int number = 0;
int flag = 1;
DWORD nret;
redisContext* c;
COleDateTime timeCreation, timeNow;
PMYDATA pDataArray = (PMYDATA)lpParam;
// printf("thread--------------name=[%s]-----tid=[%ld]\n", pDataArray->procname, GetCurrentThreadId());if (pDataArray->num > 1)
{
nret = WaitForMultipleObjects(pDataArray->num, pDataArray->hProcess, TRUE, TIMEOUT);
}
else if (pDataArray->num == 1)
{
nret = WaitForSingleObject(pDataArray->hProcess[0], TIMEOUT);
}
switch (nret)
{
case WAIT_OBJECT_0:
// 所有同名进程都结束,则写endtime
number = getProcessHandle(T2W((LPTSTR)CString(pDataArray->procname).GetBuffer(NULL)), hProcess);
if (!number)
{
sprintf_s(buff, BUFFERSIZE, "%s", removeSuffix(pDataArray->procname, ".exe"));
_strlwr_s(buff, BUFFERSIZE);
timeNow = COleDateTime::GetCurrentTime();
sprintf_s(endtime, "%02d:%02d:%02d", timeNow.GetHour(), timeNow.GetMinute(), timeNow.GetSecond(), BUFFERSIZE);
sprintf_s(buffer, "rpush %s|%s|%04d-%02d-%02d endtime|%s", mac, buff, timeNow.GetYear(), timeNow.GetMonth(), timeNow.GetDay(), endtime);
// 将进程结束时间写入 redis
c = redisConnect(redisip, redisport);
if (c->err)
{
printf("Connect to redisServer failed:%s\n", c->errstr);
redisFree(c);
return -1;
}
if (rpushString(c, buffer))
{
printf("setString error [%s]\n", buffer);
}
redisFree(c);
}
break;
case WAIT_TIMEOUT:
// 超时,退出
;;
break;
case WAIT_ABANDONED_0:
;;
break;
case WAIT_FAILED:
// 函数调用失败,比如传递了一个无效的句柄
;;
break;
}
return 0;
}
4 将监控事件做成定时事件,30秒跑一次
timer_id = timeSetEvent(TIMEOUT+1000, 1, (LPTIMECALLBACK)onTimeFunc, DWORD(1), TIME_PERIODIC);
5 套上SCManager框架,将程序做成服务,把状态传入SCManager