常州市润邦电子科技有限公司

热保护器测试专业供应商

 

VC 服务程序

1、写一个服务的CNTService类

  /*********************************************************************  
  **   文件名:   后台服务器操作;  
  **   描述:       主函数名:Run();  
  **   功能:       启动服务线程,接收服务管理器控制消息.  
  **--------------------------------------------------------------------  
  *********************************************************************/  
  //////////////////////////////////////////////////////////////////////  
  //  
  //   NTService.cpp:   implementation   of   the   CNTService   class.//  
  //  
  //////////////////////////////////////////////////////////////////////  
   
  #include   "stdafx.h"  
  #include   "Resource.h"  
  #include   "NTService.h"  
   
  DWORD   CNTService::dwThreadId;  
  LPSTR   CNTService::m_lpServiceName;                 //服务程序内部名称,名字不能有空格  
  LPSTR   CNTService::m_lpServiceDisplayName;   //SERVICE程序在管理器中的显示名称,任意字符  
  TCHAR   CNTService::m_lpServicePathName[512];         //SERVICE程序的EXE文件路径  
  CNTService   *   CNTService::m_pService;  
  SERVICE_STATUS CNTService::m_ssServiceStatus   ;//SERVICE程序的状态struct  
  SERVICE_STATUS_HANDLE CNTService::m_sshServiceStatusHandle   ;//SERVICE程序状态的HANDLE  
   
  //////////////////////////////////////////////////////////////////////  
  //   Construction/Destruction  
  //////////////////////////////////////////////////////////////////////  
   
  CNTService::CNTService()  
  {  
   
          GetModuleFileName(NULL,   m_lpServicePathName,   512);   //取当前执行文件路径  
           
          m_lpServiceName                       =   "Service";     //服务名称                      
          m_lpServiceDisplayName         =   "SOECOM";     //显示的名称  
          m_pService   =   this   ;  
          m_ssServiceStatus.dwServiceType   =   SERVICE_WIN32_OWN_PROCESS;  
          m_ssServiceStatus.dwServiceSpecificExitCode   =   0   ;  
  }  
   
  CNTService::~CNTService()  
  {  
   
  }  
   
  /*********************************************************************  
  **   将执行文件安装进NT   SERVICE管理器内  
  *********************************************************************/  
  BOOL   CNTService::InstallService()    
  {  
          SC_HANDLE   schSCManager;             //打开SCM用的句柄  
          SC_HANDLE   schService;                 //建立SERVICE用的句柄  
   
          schSCManager   =   OpenSCManager(                 //调用打开SERVICE管理器API  
 NULL,                 //机器名称,设置NULL为本地机器  
 NULL,                 //数据库名称,NULL为缺省数据库  
 SC_MANAGER_CREATE_SERVICE   //或   SC_MANAGER_ALL_ACCESS  
  );                                             //希望打开的操作权限,详见MSDN  
   
          if(   schSCManager   )                 //   如果打开SERVICE管理器成功  
          {  
                  schService   =   CreateService(                 //调用建立SERVICE的API  
                          schSCManager,                                 //SERVICE管理器数据库的句柄  
                          TEXT(m_lpServiceName),                         //服务名称  
                          TEXT(m_lpServiceDisplayName),                 //显示的名称  
                          SERVICE_ALL_ACCESS,                         //希望得到的运行权限  
                          SERVICE_WIN32_OWN_PROCESS,         //SERVICE的类型  
                          SERVICE_AUTO_START,                         //启动的方式  
                          SERVICE_ERROR_NORMAL,                 //错误控制类型  
                          TEXT(m_lpServicePathName),                 //可执行文件的路径名  
                          NULL,                 //一组服务装入时的顺序  
                          NULL,                 //检查人标记  
                          _T("RPCSS\0"),                 //从属  
                          NULL,                 //本地USER名  
                          NULL);                 //密码  
   
                  if(   schService   )         //如果建立SERVICE成功  
                  {  
     //修改描述  
     ChangeServiceConfig2(schService,SERVICE_CONFIG_DESCRIPTION,NULL); 
     CloseServiceHandle(schService);                 //释放SERVICE句柄,准备退出  
                  }else  
                  {  
                          return   FALSE   ;   //建立SERVICE失败返回  
                  }  
                  CloseServiceHandle(schSCManager);                 //释放SERVICE管理器句柄  
          }else  
          {  
                  return   FALSE;   //打开管理器失败返回  
          }  
          return   TRUE;   //一切正常返回    
  }  
   
  /*********************************************************************  
  **   将SERVICE程序从SCM管理器中移走  
  *********************************************************************/  
  BOOL   CNTService::RemoveService()    
  {  
          SC_HANDLE                 schSCManager;         //打开SCM用的句柄  
          SC_HANDLE                 schService;                 //建立SERVICE用的句柄  
   
          schSCManager   =   OpenSCManager(                 //调用打开SERVICE管理器API  
  NULL,                 //机器名称,设置NULL为本地机器  
  NULL,                 //数据库名称,NULL为缺省数据库  
  SC_MANAGER_ALL_ACCESS   //希望打开的操作权限,详见MSDN  
  );                                              
   
          if(   schSCManager   )                 //   如果打开SERVICE管理器成功  
          {  
                  schService   =   OpenService(         //获取SERVICE控制句柄的API  
                          schSCManager,                         //SCM管理器句柄  
                          m_lpServiceName,                 //SERVICE内部名称,控制名称  
                          SERVICE_ALL_ACCESS);         //打开的权限,删除就要全部权限  
   
                  if(   schService   )         //如果获取SERVICE句柄成功  
                  {  
                          if(   ControlService(schService,   SERVICE_CONTROL_STOP,   &m_ssServiceStatus)   )  
                          {       //直接向SERVICE发STOP命令,如果能够执行到这里,说明SERVICE正运行  
                                  //那就需要停止程序执行后才能删除  
                                  Sleep(3000)   ;   //等3秒使系统有时间执行STOP命令  
                                  while(   QueryServiceStatus(schService,   &m_ssServiceStatus)   )  
                                  {                                                                                         //循环检查SERVICE状态  
                                          if(m_ssServiceStatus.dwCurrentState   ==   SERVICE_STOP_PENDING)  
                                          {                                         //如果SERVICE还正在执行(PENDING)停止任务  
                                                  Sleep(1000)   ;         //那就等1秒钟后再检查SERVICE是否停止OK  
                                          }else   break   ;//STOP命令处理完毕,跳出循环  
                                  }//循环检查SERVICE状态结束  
                                  if(m_ssServiceStatus.dwCurrentState   !=   SERVICE_STOPPED)  
                                  {                                         //如果SERVICE接受STOP命令后还没有STOPPED  
                                          return   FALSE;         //那就返回FALSE报错,用GetLastError取错误代码  
                                  }  
                          }  
                          //删除指令在这里  
                          if(!   DeleteService(schService)   )         //删除这个SERVICE  
                          {  
                                  CloseServiceHandle(schService);                 //释放SERVICE控制句柄  
                                  return   FALSE;         //如果删除失败返回  
                          }else   CloseServiceHandle(schService);         //释放SERVICE控制句柄  
                  }else   //取SERVICE句柄不成功  
                  {  
                          return   FALSE;   //获取SERVICE句柄失败,或没有找到SERVICE名字返回  
                  }  
                  CloseServiceHandle(schSCManager);   //释放SCM管理器句柄  
          }else         //打开管理器不成功  
          {          
                  return   FALSE;   //打开管理器失败返回  
          }  
          return   TRUE;   //正常删除返回  
  }  
   
  /*********************************************************************  
  **   从系统中取最后一次错误代码,并转换成字符串返回  
  *********************************************************************/  
  LPTSTR   CNTService::GetLastErrorText(   LPTSTR   lpszBuf,   DWORD   dwSize   )    
  {  
          DWORD   dwRet;  
          LPTSTR   lpszTemp   =   NULL;  
   
          dwRet   =   FormatMessage(   FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_ARGUMENT_ARRAY,  
  NULL,  
  GetLastError(),  
  LANG_NEUTRAL,  
  (LPTSTR)&lpszTemp,  
  0,  
  NULL   );  
   
          //   supplied   buffer   is   not   long   enough  
          if(!dwRet||((long)dwSize<(long)dwRet+14))  
  lpszBuf[0]   =   TEXT('\0');  
          else{  
                  lpszTemp[lstrlen(lpszTemp)-2]   =   TEXT('\0');     //remove   cr   and   newline   character  
                  _stprintf(   lpszBuf,   TEXT("%s   (%ld)"),   lpszTemp,   GetLastError()   );  
          }  
   
          if   (   lpszTemp   )  
                  LocalFree((HLOCAL)   lpszTemp   );  
   
          return   lpszBuf;  
  }  
   
  /*********************************************************************  
  **   执行缺省的服务控制Dispatcher,服务开始前执行的缺省注册  
  *********************************************************************/  
  BOOL   CNTService::StartDispatch()    
  {  
          SERVICE_TABLE_ENTRY   DispatchTable[]   =    
          {    
                  {m_lpServiceName,ServiceMain},  
                  {NULL,   NULL}                          
          };                                                         //如果只有一个SERVICE就定义成2,如果有  
  //二个以上的SERVICE在一个文件里,这个  
  //表就要定义成3维或更多  
          m_bService   =   TRUE   ;  
          if(   !StartServiceCtrlDispatcher(DispatchTable))  
                  return   FALSE;  
          return   TRUE;  
  }  
   
  /*********************************************************************  
  **   服务程序开始的主程序,主要的初始化及主体服务程序均在此,  
  **   此函数内须处理STOP、PAUSE、CONTINUE等事件  
  *********************************************************************/  
  void   WINAPI   CNTService::ServiceMain(DWORD   dwArgc,   LPTSTR   *lpszArgv)  
  {  
          m_sshServiceStatusHandle   =    
                  RegisterServiceCtrlHandler(m_lpServiceName,   ServiceHandle);  
          if(!m_sshServiceStatusHandle){  
                  AddToMessageLog("RegisterServiceCtrlHandler   Error!");  
                  return   ;  
          }  
   
          if(SetSCMStatus(SERVICE_START_PENDING,   NO_ERROR,3000)){  
                  m_pService->dwThreadId   =   GetCurrentThreadId()   ;  
                  if(m_pService->Initialize()){  
                          m_pService->Run();  
                          m_pService->UnInitialize();  
                  }  
          }  
          SetSCMStatus(SERVICE_STOPPED,   NO_ERROR,   0);  
  }  
   
  /*********************************************************************  
  **   此函数接受系统发来的STOP、PAUSE,并做出相应处理发给Service_Main,  
  **   每一个指令执行后需报告当前状态给SCM管理器  
  *********************************************************************/  
  void   WINAPI   CNTService::ServiceHandle(DWORD   dwControl)  
  {  
          switch(dwControl){  
          case   SERVICE_CONTROL_STOP:  
                  m_pService->Stop()   ;  
                  SetSCMStatus(SERVICE_STOP_PENDING,   NO_ERROR,   3000);  
                  PostThreadMessage(m_pService->dwThreadId,   WM_QUIT,   0,   0   )   ;  
                  break;  
          case   SERVICE_CONTROL_PAUSE:  
                  m_pService->Pause()   ;  
                  break;  
          case   SERVICE_CONTROL_CONTINUE:  
                  m_pService->Continue()   ;  
                  break;  
          case   SERVICE_CONTROL_INTERROGATE:  
                  break;  
          default:  
                  break;  
          }  
  }  
   
  /*********************************************************************  
  **   将成功信息加进系统EVENT管理器中  
  *********************************************************************/  
  void   CNTService::AddToMessageLog(LPCTSTR   lpszMsg)  
  {  
          TCHAR         szMsg[256];  
          HANDLE       hEventSource;  
          LPCTSTR     lpszStrings[2];  
   
          if(!m_pService->m_bService){  
                  printf("%s",   lpszMsg)   ;  
                  return   ;  
          }  
   
          //   Use   event   logging   to   log   the   error.  
           
          hEventSource   =   RegisterEventSource(0,   m_lpServiceName);  
   
  _stprintf(szMsg,   TEXT("\n%s   提示信息:   %d"),   m_lpServiceDisplayName,   GetLastError());  
  lpszStrings[0]   =   szMsg;  
          lpszStrings[1]   =   lpszMsg;  
   
          if(hEventSource   !=   NULL){  
   
                  ReportEvent(hEventSource,     //   handle   of   event   source  
  EVENTLOG_SUCCESS,             //   event   type  
  0,                                           //   event   category  
  0,                                           //   event   ID  
  NULL,                                     //   current   user's   SID  
  2,                                           //   number   of   strings   in   lpszStrings  
  0,                                           //   no   bytes   of   raw   data  
  lpszStrings,                       //   array   of   error   strings  
  NULL);                                   //   no   raw   data  
                  (VOID)   DeregisterEventSource(hEventSource);  
          }  
  }  
   
  /*********************************************************************  
  **   将错误信息加进系统EVENT管理器中;  
  *********************************************************************/  
  void   CNTService::AddToErrorMessageLog(LPCTSTR   lpszMsg)  
  {  
          TCHAR         szMsg[256];  
          HANDLE       hEventSource;  
          LPCTSTR     lpszStrings[2];  
   
          if(!m_pService->m_bService){  
                  printf("%s",   lpszMsg)   ;  
                  return   ;  
          }  
          //   Use   event   logging   to   log   the   error.  
           
          hEventSource   =   RegisterEventSource(0,   m_lpServiceName);  
   
          _stprintf(szMsg,   TEXT("\n%s   提示信息:   %d"),   m_lpServiceDisplayName,   GetLastError());  
          lpszStrings[0]   =   szMsg;  
          lpszStrings[1]   =   lpszMsg;  
   
          if(hEventSource   !=   NULL){  
   
                  ReportEvent(hEventSource, //   handle   of   event   source  
  EVENTLOG_ERROR_TYPE, //   event   type  
  0, //   event   category  
  0, //   event   ID  
  NULL, //   current   user's   SID  
  2, //   number   of   strings   in   lpszStrings  
  0, //   no   bytes   of   raw   data  
  lpszStrings, //   array   of   error   strings  
  NULL); //   no   raw   data  
                  (VOID)   DeregisterEventSource(hEventSource);  
          }  
   
  }  
   
  /*********************************************************************  
  **   将警告信息加进系统EVENT管理器中;  
  *********************************************************************/  
  void   CNTService::AddToWarningMessageLog(LPCTSTR   lpszMsg)  
  {  
          TCHAR         szMsg[256];  
          HANDLE       hEventSource;  
          LPCTSTR     lpszStrings[2];  
   
          if(!m_pService->m_bService){  
                  printf("%s",   lpszMsg)   ;  
                  return   ;  
          }  
   
          //   Use   event   logging   to   log   the   error.  
           
          hEventSource   =   RegisterEventSource(0,   m_lpServiceName);  
   
          _stprintf(szMsg,   TEXT("\n%s   提示信息:   %d"),   m_lpServiceDisplayName,   GetLastError());  
          lpszStrings[0]   =   szMsg;  
          lpszStrings[1]   =   lpszMsg;  
   
          if(hEventSource   !=   NULL){  
   
                  ReportEvent(hEventSource,         //   handle   of   event   source  
      EVENTLOG_WARNING_TYPE,       //   event   type  
      0,                                               //   event   category  
      0,                                               //   event   ID  
      NULL,                                         //   current   user's   SID  
      2,                                               //   number   of   strings   in   lpszStrings  
      0,                                               //   no   bytes   of   raw   data  
      lpszStrings,                           //   array   of   error   strings  
      NULL);                                       //   no   raw   data  
                  (VOID)   DeregisterEventSource(hEventSource);  
          }  
  }  
   
  /*********************************************************************  
  **   将程序当前状态报告给SCM管理器,使管理器的显示与当前程序同步;  
  *********************************************************************/  
  BOOL   CNTService::SetSCMStatus(DWORD   dwCurrentState,  
      DWORD   dwWin32ExitCode,  
      DWORD   dwWaitHint)  
  {  
          static   DWORD   dwCheckPoint   =   1;  
          BOOL   fResult   =   TRUE;  
   
          if   (dwCurrentState   ==   SERVICE_START_PENDING)  
                  m_ssServiceStatus.dwControlsAccepted   =   0;  
          else  
                  m_ssServiceStatus.dwControlsAccepted   =   SERVICE_ACCEPT_STOP;  
   
          m_ssServiceStatus.dwCurrentState   =   dwCurrentState;  
          m_ssServiceStatus.dwWin32ExitCode   =   dwWin32ExitCode;  
          m_ssServiceStatus.dwWaitHint   =   dwWaitHint;  
   
          if   (   (   dwCurrentState   ==   SERVICE_RUNNING   )   ||  
                  (   dwCurrentState   ==   SERVICE_STOPPED   )   )  
                  m_ssServiceStatus.dwCheckPoint   =   0;  
          else  
                  m_ssServiceStatus.dwCheckPoint   =   dwCheckPoint++;  
   
   
          //   Report   the   status   of   the   service   to   the   service   control   manager.  
          //  
          if   (!(fResult   =   SetServiceStatus(   m_sshServiceStatusHandle,   &m_ssServiceStatus))){  
                  AddToMessageLog(TEXT("SetServiceStatus"));  
          }  
          return   fResult;  
  }  
   
  /*********************************************************************  
  **    
  *********************************************************************/  
  BOOL   CNTService::Initialize()  
  {  
          if(!SetSCMStatus(SERVICE_RUNNING,   NO_ERROR,   0))  
                  return   FALSE   ;  
   
  return   TRUE;  
  }  
   
  /*********************************************************************  
  **    
  *********************************************************************/  
  void   CNTService::UnInitialize()  
  {  
   
  }  
   
  /*********************************************************************  
  **    
  *********************************************************************/  
  void   CNTService::Stop()  
  {  
   
  }  
   
  /*********************************************************************  
  **    
  *********************************************************************/  
  void   CNTService::Pause()  
  {  
   
  }  
   
  /*********************************************************************  
  **    
  *********************************************************************/  
  void   CNTService::Continue()  
  {  
   
  }  
   
  /*********************************************************************  
  **   主函数;  
  *********************************************************************/  
  void   CNTService::Run()    
  {  
  //在此调用服务的实际程序  
  //进入消息循环;  
  MSG   msg;  
  while(GetMessage(&msg,0,0,0)){  
  AddToMessageLog(_T("收到消息"));  
  DispatchMessage(&msg);  
  }  
  }  

 

2、CNTService的头文件

 //   NTService.h:   interface   for   the   CNTService   class.  
  //  
  //////////////////////////////////////////////////////////////////////  
   
  #if   !defined(AFX_NTSERVICE_H__4EF874F0_2934_11D3_AFC2_5254ABDD3C8E__INCLUDED_)  
  #define   AFX_NTSERVICE_H__4EF874F0_2934_11D3_AFC2_5254ABDD3C8E__INCLUDED_  
   
  #if   _MSC_VER   >   1000  
  #pragma   once  
  #endif   //   _MSC_VER   >   1000  
   
  #include   <windows.h>  
  #include   <winsvc.h>  
  #include   <stdio.h>  
  #include   <tchar.h>  
   
  class   CNTService      
  {  
  public:  
          BOOL   m_bService;  
          virtual   void   Continue();  
          virtual   void   Pause();  
          virtual   void   Stop();  
          virtual   void   UnInitialize();  
          virtual   void   Run();  
          virtual   BOOL   Initialize();  
           
          static   CNTService   *   m_pService;  
          static   void   WINAPI   ServiceHandle(DWORD   dwControl);  
          static   void   WINAPI   ServiceMain(DWORD   dwArgc,   LPTSTR   *lpszArgv);  
          static   BOOL   SetSCMStatus(DWORD   dwCurrentState,   DWORD   dwWin32ExitCode,   DWORD   dwWaitHint);  
          static   void   AddToMessageLog(LPCTSTR   lpszMsg);  
          static   void   AddToErrorMessageLog(LPCTSTR   lpszMsg)   ;  
  static   void   AddToWarningMessageLog(LPCTSTR   lpszMsg);  
   
          BOOL   StartDispatch();  
          BOOL   RemoveService();         //将服务程序从SCM管理器中删除掉  
          BOOL   InstallService();         //将服务程序安装进SCM管理器中  
   
          LPTSTR   GetLastErrorText(LPTSTR   lpszBuf,   DWORD   dwSize);  
   
          CNTService();                         //构造  
          virtual   ~CNTService();         //析构  
   
          static   LPSTR   m_lpServiceName;                 //服务程序内部名称,名字不能有空格  
          static   LPSTR   m_lpServiceDisplayName;   //SERVICE程序在管理器中的显示名称,任意字符  
  private:  
          static   DWORD   dwThreadId   ;  
          static   TCHAR   m_lpServicePathName[512];         //SERVICE程序的EXE文件路径  
          static   SERVICE_STATUS   m_ssServiceStatus   ;//SERVICE程序的状态struct  
          static   SERVICE_STATUS_HANDLE   m_sshServiceStatusHandle   ;//SERVICE程序状态的HANDLE  
  };  
   
#endif   //   !defined(AFX_NTSERVICE_H__4EF874F0_2934_11D3_AFC2_5254ABDD3C8E__INCLUDED_)  
 
  /*********************************************************************  
  *********************************************************************  
  *********************************************************************  
  *********************************************************************  
  *********************************************************************/    

 

3、建一个(支持MFC)的控制台程序,在MAIN函数中加入下边的代码。

int   _tmain(int   argc,   TCHAR*   argv[],   TCHAR*   envp[])  
{  
 int   nRetCode   =   0;  
 CNTService   cService;  
   
 SERVICE_TABLE_ENTRY   dispatchTable[]   =  
 {  
  {   TEXT(cService.m_lpServiceName),   (LPSERVICE_MAIN_FUNCTION)cService.ServiceMain},  
  {   NULL,   NULL   }  
 };  
 //   initialize   MFC   and   print   and   error   on   failure  
 if(!AfxWinInit(::GetModuleHandle(NULL),NULL,::GetCommandLine(),0)){  
  cerr   <<   _T("程序启动错误!")   <<   endl;  
  nRetCode=1;  
 }else{  
  if((argc>1)&&((*argv[1]=='-')||(*argv[1]=='/'))){  
   if(_stricmp("install",argv[1]+1)==0){  
    cout   <<   _T("正在安装服务器...")   <<   endl;  
    if(cService.InstallService())  
     cout   <<   _T("服务器安装成功!")   <<   endl;  
    else  
     cout   <<   _T("服务器安装失败!")   <<   endl;  
   }else   if(_stricmp("remove",argv[1]+1)==0){  
    cout   <<   _T("正在删除服务器...")   <<   endl;  
    if(cService.RemoveService())  
     cout   <<   _T("服务器删除成功!")   <<   endl;  
    else  
     cout   <<   _T("服务器删除失败!")   <<   endl;  
   }   
  }else{  
   cout   <<   _T("-install   安装服务器")   <<   endl;  
   cout   <<   _T("-remove   卸载服务器")   <<   endl;  
   cout   <<   _T("正在启动服务器,请稍候...")   <<   endl;  
   if(!cService.StartDispatch())  
    cService.AddToErrorMessageLog(TEXT("服务器启动失败!"));  
  }  
 }  
 return   nRetCode;  
}  

 

 

posted on 2010-11-24 12:15  常州市润邦电子科技  阅读(2642)  评论(0编辑  收藏  举报

导航