Wingdows下各种类型的守护进程的写法

写一个C++程序,监控另一个进程,发现该进程关掉了就自动把它重启。

#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <tchar.h>

using namespace std;

int _tmain(int argc, TCHAR *argv[])
{
    STARTUPINFO si;
 
    PROCESS_INFORMATION pi; //
进程信息:

ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));
    do{
          //
创建子进程,判断是否执行成功
          if(!CreateProcess( NULL,"cmd /c d://1.jpg",NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
          {
                  cout << "
创建进程失败.." << GetLastError() << endl;
                  system("pause"); //
用于测试
                   return 0;
           }
           //
进程执行成功,打印进程信息
           cout << "
以下是子进程的信息:" << endl;
           cout << "
进程ID pi.dwProcessID: " << pi.dwProcessId << endl;
          cout << "
线程ID pi.dwThreadID : " << pi.dwThreadId << endl;
          //
等待知道子进程退出...
          WaitForSingleObject( pi.hProcess, INFINITE);//
检测进程是否停止 

 // while (WAIT_TIMEOUT == WaitForSingleObject( pi.hProcess, 50))  //检测进程是否停止 (INFINITE)
 // {
 //  //检查进程当前状态,返回0表示正在运行,返回非0,表示暂停
 //  if (0 != ResumeThread(pi.hProcess))
 //  {
 //   break;
 //  }
 // }
          //WaitForSingleObject()
函数检查对象的状态,如果是未确定的则等待至超时
           //
子进程退出
        cout << "
子进程已经退出..." << endl;
          //
关闭进程和句柄
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
        //system("pause");//
执行完毕后等待
    }while(true);//
如果进程推出就再次执行方法
    exit(0);
    return 0;
}

 

//GetThreadPriority();     //获得进程状态
//ResumeThread()

 

 

 

在程序中启动另外一个进程


#include "stdafx.h"
#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <ShellAPI.h>
using namespace std;

int _tmain(int argc, TCHAR *argv[])
{

 

//#include   <ShellAPI.h>
 //wchar_t lpFile[] = L"E://Test//Test.exe";
 SHELLEXECUTEINFO   ExeInfo;  
 ZeroMemory   (   &ExeInfo,   sizeof(   SHELLEXECUTEINFO)   );  
 ExeInfo.cbSize   =   sizeof(   SHELLEXECUTEINFO   );  
 ExeInfo.lpFile   =   L"E://Test//Test.exe";
 ExeInfo.lpDirectory   =   NULL;  
 ExeInfo.lpParameters   =   NULL;  
 ExeInfo.fMask   =   SEE_MASK_NOCLOSEPROCESS   ;  
 ExeInfo.nShow   =   SW_MAXIMIZE;//SW_HIDE;  

 //try  
 //{  
  ShellExecuteEx   (   &ExeInfo   );  
  //this->Enabled   =   false;  
 //}  
 //catch   (Exception   &exception)  
 //{  
 // //this->Enabled   =   true;  
 // Application->ShowException(&exception);  
 //}  

 //this->Hide();  
 for   (   ;   ;   )  
 {  
  //Application->ProcessMessages();  
  if   (   WAIT_TIMEOUT   !=   WaitForSingleObject   (   ExeInfo.hProcess,   INFINITE   )   )   break;  
  //if   (   g_blExit   )   break;     //   Exit   the   Application  
 }  
 //this->Show();  
 //this->Enabled   =   true;  
 //this->SetFocus();  
 //this->BringToFront();  

 

}

 

 

windows下监控进程的脚本

相信大家都有这样的需求,某程序(进程)在运行的时候可能挂掉,需要去监控该程序,并在它挂掉的时候重启之,确保该程序能一直运行。比如土net就经常挂,需要监控程序去监控。Linux下面似乎有守护进程的概念,Windows下面其实也很简单,dos批处理就可以搞定 :-)

需要了解如下几个命令,tasklist + findpingtasklist是列出所有进程,可以指定只列出某用户的进程,用/FI参数过滤。find /C可以去tasklist的结果中查找指定进程名,并输出个数。

还有个问题是如何设置每隔一段时间去检测进程是否在运行,我用的是ping命令自带的延迟参数-w,将IP地址设置成一个空地址,比如0.0.0.1,这样该命令会一直ping,直到一定n*w 毫秒后才返回(nw分别是参数-n-w指定的值)。

示例程序如下,红色部分需要根据需求进行替换,enjoy it


:RESTART
tasklist /FI "username eq bigtree" | find /C "java" > temp.txt
set /p num= < temp.txt
del /F temp.txt
echo %num%

if "%num%" == "0"        start /D "E:/User/bigtree/program/comparison/" pos

ping -n 10 -w 2000 0.0.0.1 > temp.txt
del /F temp.txt
goto RESTART



注意1goto语句是将监控程序设置成死循环,哇咔咔。
注意2:可以用start /D path program去异步调用program程序,也就是不等program指定完毕就执行下面的语句,因此可以设置固定间隔(n*w毫秒)去监测。
      
如果用call program则是同步调用,会等待program执行完毕,这样延迟就用不着了。

 

 

 

最近几天加班加疯掉了,天天晚上没法睡。开发部的一个核心程序总是会自己宕机,然后需要手工去起,而这个服务的安全级别又很高,只有我可以操作,搞得我晚上老没法睡,昨晚实在受不了了,想起以前在hp-ux下写的shell守护进程,这回搞个windows下的bat版守护程序吧,当时晚上思路已经很迟钝了,就叫了个兄弟让他写了,上去后运行效果不错,至少昨晚我安心睡了7小时。

 

早上来把程序改完善一些,增加了记录等功能。

实现:

检查是否有notepad,要用的话就算成自己的进程名,如果进程宕了就过会自动重启(会在当前目录下生成一个start.bat

 

  @echo off

 

set _task=notepad.exe

set _svr=c:/windows/notepad.exe

set _des=start.bat

 

:checkstart

for /f "tokens=5" %%n in ('qprocess.exe ^| find "%_task%" ') do (

 if %%n==%_task% (goto checkag) else goto startsvr

)

 

 

 

:startsvr

echo %time%

echo ********程序开始启动********

echo 程序重新启动于 %time% ,请检查系统日志 >> restart_service.txt

echo start %_svr% > %_des%

echo exit >> %_des%

start %_des%

set/p=.<nul

for /L %%i in (1 1 10) do set /p a=.<nul&ping.exe /n 2 127.0.0.1>nul

echo .

echo Wscript.Sleep WScript.Arguments(0) >%tmp%/delay.vbs

cscript //b //nologo %tmp%/delay.vbs 10000

del %_des% /Q

echo ********程序启动完成********

goto checkstart

 

 

:checkag

echo %time% 程序运行正常,10秒后继续检查..

echo Wscript.Sleep WScript.Arguments(0) >%tmp%/delay.vbs

cscript //b //nologo %tmp%/delay.vbs 10000

goto checkstart

 

 

 

怎么实现一个:判断指定进程有无响应的功能函数.
已知条件为:一个进程ID,求这个进程有无响应;VC平台实现.
我在网络查找一些资料,copy后得出以下一个程序,但不能检测出结果,运行时会出错.

接触C++不是很长时间,希望大家能帮帮我,解决这个问题,谢谢.
如果还有其它方法,请给予提示.谢谢.

///////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <stdio.h>


typedef  struct  tagWNDINFO 

DWORD  dwProcessId; 
HWND  hWnd; 
}  WNDINFO,  *LPWNDINFO; 

BOOL CALLBACK YourEnumProc(HWND hWnd,LPARAM  lParam) 

DWORD  dwProcessId; 
GetWindowThreadProcessId(hWnd,  &dwProcessId); 
LPWNDINFO  pInfo  =  (LPWNDINFO)lParam; 
if(dwProcessId  ==  pInfo->dwProcessId) 

pInfo->hWnd  =  hWnd; 
return  FALSE; 

return  TRUE; 


HWND  GetProcessMainWnd(DWORD  dwProcessId) 

WNDINFO  wi; 
wi.dwProcessId  =  dwProcessId; 
wi.hWnd  =  NULL; 
EnumWindows(YourEnumProc,(LPARAM)&wi); 
return  wi.hWnd; 

//
如果这个进程没有窗口,函数返回NULL

/** /*/
//////////////////////////////////////////////////////////////////////////
int GetProcessAnswer(DWORD iProcessid)
{
HWND hwnd = GetProcessMainWnd(iProcessid);
//
不存在/
if(NULL == hwnd)return(-1);

typedef BOOL (WINAPI *PROCISHUNGAPPWINDOW)(HWND);
typedef BOOL (WINAPI *PROCISHUNGTHREAD)(DWORD);

//
然后定义
PROCISHUNGAPPWINDOW    m_pIsHungAppWindow;
PROCISHUNGTHREAD    m_pIsHungThread;

//
定义一个bool型,来判断当前操作系统是否是Windows NT/2000以上
//
因为不同的操作系统,判断程序是否运行正常的方式是不一样的

BOOL m_bIsNT;
BOOL bRetVal;

//
获取版本信息
OSVERSIONINFO osver = {0};

osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (!GetVersionEx(&osver))
{
bRetVal = FALSE;
}


if(bRetVal == TRUE)
{
if (osver.dwPlatformId&VER_PLATFORM_WIN32_NT)
{
m_bIsNT = TRUE;
}
else
{
m_bIsNT = FALSE;
}

}

//
获取那两个函数指针
HMODULE hUser32 = ::GetModuleHandle("user32");

if (!hUser32)
{
bRetVal = FALSE;
}


if(bRetVal == TRUE)
{
m_pIsHungAppWindow = (PROCISHUNGAPPWINDOW)
GetProcAddress( hUser32,
"IsHungAppWindow" );

m_pIsHungThread = (PROCISHUNGTHREAD) GetProcAddress( hUser32,
"IsHungThread" );

if (!m_pIsHungAppWindow && !m_pIsHungThread)
{
bRetVal = FALSE;
}

}

//
于是判断,窗口是否是正常运行,还是未响应
//
代码如下

if(m_bIsNT == TRUE)

BOOL bIsHung = m_pIsHungAppWindow(hwnd);
if(bIsHung)
{
return(-2);//
没有响应
}
else
{
return(0);//
正在运行   
}

else
{
BOOL bIsHung =m_pIsHungThread(GetWindowThreadProcessId(hwnd,NULL));
if(bIsHung)
{
return(-2);//
没有响应
}
else
{
return(0);//
正在运行   
}
}


}

//////////////////////////////////////////////////////////////////////////


int main()
{

// int iSum = int(GetProcessMainWnd(3616));//3616
是进程ID
// printf("%d",isum);
int isum = GetProcessAnswer(3616/*
这里输入进程ID*/);
printf("%d",isum);

return(0);
}

 

 

请问怎么判断一个进程是否停止响应?

DWORD   dwResult;  
    BOOL   fResponding   =   SendMessageTimeout(hwndInQuestion,  
              WM_NULL,   0,   0,   SMTO_ABORTIFHUNG,   5000,   &dwResult);  
    //   fResponding   is   TRUE   if   the   thread   is   responding   and  
    //   FALSE   if   not.  

 

 

 

整个过程是这样:  
 
有一个Server,Server一直运行,理想状态不会失去响应,同时有一个应用程序也在运行,当Server接到指令要检测那个应用程序是否还有响应,如果没有响应就Kill这个应用程序的进程,并重启这个应用程序。  
   
 
现在关键是如何检测应用程序是否还有响应,怎么样Kill掉它,怎么样重启它这三个问题。  
   
 
大家帮帮忙,这样的问题帖子很多,但都没有提供完整的例子代码,我是菜鸟,告诉我方法自己写还不太可能,需要看代码学习!   谢谢了! 问题点数:100、回复次数:30Top

1 vcleaner(我没当大哥很久了.......回复于 2004-11-10 09:47:11 得分 0

应该是如何判断进程的活动状态,呵呵,写注册表,查询注册表,然后判断其值,如果和上次比较没有改变,那么就重启。这样做有滞后,但是既然能重启系统,滞后也应该能接受吧。呵呵,如果楼主能有相关的函数或者办法实时判断状态,请告诉我!  
  Top

2 laiyiling(陌生人[MVP]回复于 2004-11-10 09:51:16 得分 25

ZT:  
 
SendMessageTimeout函数向目的窗口发一个消息,如果返回0,而且GetLastError得到0,就表示该窗口线程无响应.Top

3 vcleaner(我没当大哥很久了.......回复于 2004-11-10 09:52:15 得分 0

你可以让程序运行起来的时候写一个字符串(GetModuleFileName得到的是现在的名字和一个数字值)到注册表中的固定位置,每隔一段时间更新一下数据值,不管别人将Exe改名为什么,只要你想知道是不是你写的程序在运行,只要查询注册表就行了,如果查询的数据值多次没有改变,即说明那个程序已经当掉了,你可以重启之,呵呵,记得程序退出的时候删除注册表项。这样就可以判断是否在运行了!可以将两个程序都这么做,那么他们就能相互监控了!Top

4 DentistryDoctor(不在无聊中无奈,就在沉默中变态)回复于 2004-11-10 09:52:38 得分 0

最简单的方法是函数  
  IsHungAppWindowTop

5 DentistryDoctor(不在无聊中无奈,就在沉默中变态)回复于 2004-11-10 09:53:28 得分 5

IsHungAppWindow   Function  
   
  --------------------------------------------------------------------------------  
   
  You   call   the   IsHungAppWindow   function   to   determine   if   Microsoft   Windows   considers   that   a   specified   application   is   not   responding,   or   "hung".   An   application   is   considered   to   be   not   responding   if   it   is   not   waiting   for   input,   is   not   in   startup   processing,   and   has   not   called   PeekMessage   within   the   internal   timeout   period   of   5   seconds.    
   
  Syntax  
   
  BOOL   IsHungAppWindow(                     HWND   hWnd  
  );  
  Parameters  
   
  hWnd  
  [in]   Handle   to   the   window.    
  Return   Value  
   
  Returns   TRUE   if   the   window   stops   responding,   otherwise   returns   FALSE.   Ghost   windows   always   return   TRUE.    
   
   
  Remarks  
   
  The   Windows   timeout   criteria   of   5   seconds   is   subject   to   change.  
   
  Although   you   can   access   this   function   by   using   LoadLibrary   and   GetProcAddress   combined   in   Windows   versions   prior   to   Windows   XP,   the   function   is   not   accessible   using   the   standard   Include   file   and   library   linkage.   The   header   files   included   in   Windows   XP   Service   Pack   1   (SP1)   and   Windows   Server   2003   document   this   function   and   make   it   accessible   using   the   appropriate   Include   file   and   library   linkage.   However,   this   function   is   not   intended   for   general   use.   It   is   recommended   that   you   do   not   use   it   in   new   programs   because   it   might   be   altered   or   unavailable   in   subsequent   versions   of   Windows.    
   
  Function   Information  
   
  Minimum   DLL   Version   user32.dll    
  Header   Declared   in   Winuser.h,   include   Windows.h    
  Import   library   User32.lib    
  Minimum   operating   systems   Windows   2000    
  Top

6 oyljerry(【勇敢的心】 ㊣提拉米苏㊣)回复于 2004-11-10 10:04:31 得分 10

WaitForSingleObject等待句柄返回  
  Terminate
终止进程  
  CreateProcess
启动进程Top

7 mixtrue(忽报人间曾伏虎,泪飞顿作倾盆雨。)回复于 2004-11-10 10:09:36 得分 0

To   DentistryDoctor   :  
   
  The   function   of   IsHungAppWindow   is   testing   the   application   (specified   application   ),   not   The   process.     I   think   that   the   IsHungAppWindow   will   not   works   to   PROCESS.Top

8 ppssdd()回复于 2004-11-10 10:18:04 得分 0

DentistryDoctor(雅克医生<改行做程序员了>)   :  
  BOOL   IsHungAppWindow(HWND   hWnd);
参数hWnd怎么取呢?你发个例子可以吗?Top

9 ppssdd()回复于 2004-11-10 10:19:36 得分 0

大家的意见都很好,就是没有例子啊!   俺是菜鸟!Top

10 ppssdd()回复于 2004-11-10 10:23:21 得分 0

mixtrue  
   
 
一个正在执行的exe文件可以叫一个应用吧,   也是一个进程啊,这两个有什么区别吗?Top

11 DentistryDoctor(不在无聊中无奈,就在沉默中变态)回复于 2004-11-10 13:21:38 得分 0

FindWindow   or   EnumWindows   to   get   the   process's   main   window.Top

12 kingzaistevenzhu回复于 2004-11-10 13:35:53 得分 0

http://www.vckbase.com/bbs/prime/viewprime.asp?id=334  
  Windows  
任务管理器如何确定应用程序"没有响应"  
  (hangwire
发表于2001-12-26   15:46:46)  
   
       
最近参加的一个项目要求实现远程任务管理功能,也就是"Remote   Task   Manager"(RTM)。我把它与Windows   NT的任务管理器进行了比较,发现标准的任务管理器显示应用程序的状态(正在运行或者没有响应)。标准的任务管理器发送(通过SendMessageTimeout函数)一个消息到主应用窗口,如果函数调用失败或者超时--则应用程序的状态就是"没有响应",否则状态为"正在运行"  
       
但我发现还有一个更好的解决方法。本文将通过实例程序进行示范。这个方法的思路是通过调用User32.dll中一个未公开的函数来实现的。这个函数存在于Windows   9xWindows   NT/2000系统中,但在两个系统中的名字是不同的。Windows   9x系统中的名字为:IsHungThread,在Windows   NT/2000系统中的名字为IsHungAppWindow。下面是它们的原型:  
  BOOL   IsHungAppWindow   (  
  HWND   hWnd,   //  
主应用窗口句柄  
  )
 
 
 
  BOOL   IsHungThread   (  
  DWORD   dwThreadId,   //  
主应用窗口的线程ID  
  )
 
       
不幸的是,微软在User32.lib中没有提供这两个函数的输出。也就是说,这两个函数是未公开函数,如果要在程序中使用它们,则必须通过GetProcAddressGetModuleHandle函数动态加载:  
   
  typedef   BOOL   (WINAPI   *PROCISHUNGAPPWINDOW)   (HWND)
 
  typedef   BOOL   (WINAPI   *PROCISHUNGTHREAD)   (DWORD)
 
   
  PROCISHUNGAPPWINDOW   IsHungAppWindow
 
  PROCISHUNGTHREAD   IsHungThread
 
   
  HMODULE   hUser32   =   GetModuleHandle("user32")
 
   
  IsHungAppWindow   =   (PROCISHUNGAPPWINDOW)  
  GetProcAddress(hUser32,"IsHungAppWindow")
 
   
  IsHungThread   =   (PROCISHUNGTHREAD)  
  GetProcAddress(hUser32,"IsHungThread")
Top

13 kingzaistevenzhu回复于 2004-11-10 13:37:18 得分 10

1hwo   to   kill   process?  
  GetWindowThreadProcessId
得到进程id,OpenProcess得到进程句柄,调用TerminateProcess  
  2.hwo   to   create   process?  
  CreateProcess  
   
  Top

14 DentistryDoctor(不在无聊中无奈,就在沉默中变态)回复于 2004-11-10 13:37:43 得分 20

HWND   g_hWndToProcess=NULL;  
  BOOL   CALLBACK   EnumWindowsProc(HWND   hwnd,  
      LPARAM   nProcessID  
      )  
  {  
  DWORD   dwProcessID=0;  
  GetWindowThreadProcessId(hwnd,&dwProcessID);  
  if(dwProcessID==nProcessID)  
  {  
  char   szTitle[256];  
  TCHAR   szBuf[256];  
  ZeroMemory(szTitle,256);  
  GetClassName(hwnd,   szBuf,   256   );  
  GetWindowText(hwnd,szTitle,256);  
  if(lstrlen(szTitle)   &&   IsWindowVisible(hwnd)   &&   lstrcmp("Program",szBuf))  
  {  
  OutputDebugString(szTitle);  
  g_hWndToProcess=hwnd;  
  return   FALSE;  
  }  
   
  }  
  return   TRUE;  
  }  
   
   
  ...  
  g_hWndToProcess=NULL;  
  EnumWindows(EnumWindowsProc,nID);//nID:
目的进程的ID,必须有主窗口  
  if(NULL!=g_hWndProcess   &&   IsHungAppWindow(g_hWndToProcess))  
  {  
  ...  
  }Top

15 gooyan(超级替补)回复于 2004-11-10 19:30:55 得分 0

createmutex  
  Top

16 mixtrue(忽报人间曾伏虎,泪飞顿作倾盆雨。)回复于 2004-11-11 10:36:00 得分 0

To   :   ppssdd()    
   
 
应用程序和进程当然有差别了,详情参见os   书籍    
  Top

17 Magnus(小楼一夜听春雨)回复于 2004-11-11 10:38:45 得分 0

典型的WatchDog,  
 
讓被監視的進程定時發消息給WatchDog,  
 
超時就認定為失去響應,  
 
resetTop

18 linxy2002BugSlayer回复于 2004-11-11 15:39:55 得分 30

呵呵,是啊,对于菜鸟来说,例子才是正道!  
 
你把要求说清楚写,我帮你写一个,我的:   [email protected]Top

19 blastzgd(悟道)回复于 2004-11-11 17:21:04 得分 0

楼主这个不知算不算无理要求。  
 
你的没响应是什么意思?阻塞了?还是死循环了?  
   
  Top

20 linxy2002BugSlayer回复于 2004-11-11 20:19:56 得分 0

我写了个小例子不知道符不符合你的需要,你来向我要吧Top

21 NNBWOLF(叫花子)回复于 2004-11-11 22:00:07 得分 0

阿狼也贴点代码看看...Top

22 ppssdd()回复于 2004-11-12 14:23:32 得分 0

TO:  
  blastzgd(
边城浪子)   :  
 
window任务管理器中应用程序的状态被判为无响应时,你知道是阻塞了?还是死循环了?也是无理要求?  
  Top

23 ppssdd()回复于 2004-11-12 14:29:35 得分 0

TO:  
  linxy2002(
阿郎)   :  
       
还是你理解我啊!  
       
我给你发了消息了,多谢,你可以发给我了!~     :)Top

24 linxy2002BugSlayer回复于 2004-11-13 13:15:31 得分 0

已经发给你了,不知道是否满足你的要求Top

25 hjunxuhjun回复于 2004-11-13 14:39:05 得分 0

楼主你的应用好奇怪啊。  
 
如果程序在很忙的干活,比如处理一个消息响应很久,messagepump没有动静系统就会认为你的程序没有响应的,所以可能杀错。Top

26 hjunxuhjun回复于 2004-11-13 14:41:29 得分 0

你可以说说你这样应用理由吗?Top

27 zhouhuaikun(怀空)回复于 2004-11-13 14:48:06 得分 0

学习!Top

28 ppssdd()回复于 2004-11-15 13:53:39 得分 0

To:   hjunxu(hjun)  
          “
如果程序在很忙的干活,比如处理一个消息响应很久,messagepump没有动静系统就会认为你的程序没有响应的,所以可能杀错。”  
         
你说得很有道理,但我要实现的目的与这个没什么大的关系,因为有个重要应用是不能长时间失去响应,也就是说宁可错杀,不可漏杀,反正要重启的!  
  Top

29 ppssdd()回复于 2004-11-15 13:55:17 得分 0

TO:  
  linxy2002(
阿郎)   :  
       
已经收到,谢谢!   我已经看了,帮助很大!  
  Top

30 lnp()回复于 2004-12-21 18:36:44 得分 0

mark

 

 

 

 

 

软件名称:AlwaysUp
软件版本:v6.5.9.28
软件大小:
3.77 MB
适用平台:
Windows ALL
软件主页:http://www.coretechnologies.com/products/AlwaysUp/

软件简介:
能将可执行文件、批处理文件及快捷方式作为windows系统服务,并且进行管理和监视确保100%运行。当程序崩溃、挂起、弹出错误对话框时,AlwaysUp 能自动重启程序,并运行自定义的检查功能确保程序一直可用。AlwaysUp 能发送详细的email使你清楚地了解崩溃、重启等事件。

下载地址:http://www.coretechnologies.com/products/alwaysup/AlwaysUp_Installer.exe

 

 

 


 

 

 

 

你可能感兴趣的:(windows,exception,function,null,application,winapi)