一个完整windows 服务源代码下载地址

开发环境 vs 2010 (但方法适用于VS2005 及 VS 2008)c++ atl 版

在编译出exe以后使用release下的批处理安装卸载服务
在windows里的服务控制面板进行服务的启动和停止操作
本程序是完整的windows 服务开发框架,直接在里面添加业务代码就可以
产生一个标准的服务程序

带有一个日志文件

http://b.qjwm.com/down.aspx?down=ok&filepath=dante300%2fwindows+service%2fwindow+service.rar

 知识性说明

原文出处:http://topic.csdn.net/u/20070126/09/c1d1279a-bbac-45b9-8e88-835b8956d97e.html

1,调试:怎样才能在VS2005中调试。 
看CatlServiceModuleT中的WinMain,检查输入参数有效就调用START。START先检测服务有没有注册过,没有注册的就直接返回退出。所以一定要先注册。检测到有注册就查看是否注册为LocalService(也就是   -Service),如果为LocalService就把_ServiceMain连接到SCM(服务管理器),但在调试模式下不能连接成功,或者必须由SCM来启动,要不它认为已启动。所以不能注册为服务,只能注册为RegSever(-RegSever)。调试完后,再注册为服务。如果只有在服务里面才出错,可用CatlServiceModuleT带的LogEvent   把调试信息写到windows事件里面。MSDN中讲可以服务进程连到VS2005我没试过,因为全在RegSever模式下解决了。 
  
2,更改服务的启动模式。 
没找到更改服务启动模式的方法。查看代码发现在CatlServiceModuleT的Install中写死的。 
                  SC_HANDLE   hService   =   ::CreateService( 
                            hSCM,   m_szServiceName,   m_szServiceName, 
                            SERVICE_ALL_ACCESS,   SERVICE_WIN32_OWN_PROCESS, 
                            SERVICE_DEMAND_START,   SERVICE_ERROR_NORMAL, 
                  szFilePath,   NULL,   NULL,   _T( "RPCSS\0 "),   NULL,   NULL); 
  
SERVICE_DEMAND_START表示手动在SCM启动。有个方法,在重写的RegisterAppId用ChangeServiceConfig修改,但看一下ChangeServiceConfig的参数,好多呀,太麻烦。加上我觉得写一个服务就应该自动启动,什么时候处理任务是服务的事,而且不想用了可以在SCM里禁用。所以我做了一个不道德的地方――把CatlServiceModuleT源程序改了。把SERVICE_DEMAND_START改为SERVICE_AUTO_START。 
                  SC_HANDLE   hService   =   ::CreateService( 
                            hSCM,   m_szServiceName,   m_szServiceName, 
                            SERVICE_ALL_ACCESS,   SERVICE_WIN32_OWN_PROCESS, 
                            SERVICE_AUTO_START,   SERVICE_ERROR_NORMAL, 
                  szFilePath,   NULL,   NULL,   _T( "RPCSS\0 "),   NULL,   NULL); 
谁叫他不道德没流一个好的方法。当然你可以用ChangeServiceConfig,自己查一下。 
  
              3,暂停和继续, 
我想用暂停和继续来实现配置的更新,因为不想改配置的时候,要停止服务,再启动,那样服务会断。还有就是用命名管道或全局消息让配置工具和服务通讯,但太麻烦,我只是想重新应有配置。 
              第一个问题,在SMC中暂停和继续的菜单是灰的。找了很久,找到::SetServiceStatus(m_hServiceStatus,   &m_status)   ,还好m_status是Public   ,用m_status.   dwControlsAccepted=m_status.dwControlsAccepted|   SERVICE_ACCEPT_PAUSE_CONTINUE;搞定。 
              另一个问题,重写了OnPause但更本没进去。用LogEvent调试,发现CatlServiceModuleT的_Handler都没进去(LocalService就把_ServiceMain连接到SCM,_ServiceMain调用ServiceMain,ServiceMain中注册Handler为SCM处理函数,处理STOP、PAUSE等),_Handler   中是这样调用的((T*)_pAtlModule)-> Handler(dwOpcode);   不知到_pAtlModule是指向谁的实例。我重写了Handler,就可以进来了。在自己的Handler中调用PAUSE,OnContinue后,就调用父类的Handler。 
  
  
终于完成了,代码如下,工作线程没写出来。 
  
class   CNVSStoreServerModule   :   public   CAtlServiceModuleT <   CNVSStoreServerModule,   IDS_SERVICENAME   > 

private: 
          CWorkThread   *   pWork;   //工作类,没写出来。 
public   : 
          DECLARE_LIBID(LIBID_NVSStoreServerLib) 
          DECLARE_REGISTRY_APPID_RESOURCEID(IDR_NVSSTORESERVER,   "{CF40AF29-C742-4D52-906C-5915A611F2D6} ") 
          HRESULT   InitializeSecurity()   throw() 
          { 
                  return   S_OK; 
          } 
          void   OnPauze()   throw() 
          { 
                  SetEvent(pWork-> mServerStopEvent); 
                  SetServiceStatus(SERVICE_PAUSED); 
                  __super::OnPause(); 
          } 
          void   OnStop()   throw() 
          { 
                  SetEvent(pWork-> mServerStopEvent); 
                  WaitForSingleObject(pWork-> mCanStopEvent,INFINITE); 
                  __super::OnStop(); 
          } 
          void   Handler(DWORD   dwOpcode)   throw() 
          { 
                  switch   (dwOpcode) 
                  { 
                  case   SERVICE_CONTROL_PAUSE: 
                            OnPauze(); 
                            break; 
                  case   SERVICE_CONTROL_CONTINUE: 
                            OnContinue(); 
                            break; 
                  } 
                  __super::Handler(dwOpcode); 
          } 
          CServiceStatus   GetServiceStatus()   throw() 
          { 
                  return   this-> m_ServiceStatus; 
          } 
          void   OnContinue(   )   throw(   ) 
          { 
                  SetServiceStatus(SERVICE_RUNNING); 
                  __super::OnContinue(); 
          } 
          HRESULT   PreMessageLoop(int   nShowCmd)   throw() 
          { 
                  m_status.dwControlsAccepted   =m_status.dwControlsAccepted   |   SERVICE_ACCEPT_PAUSE_CONTINUE; 
                  HRESULT   hr   =   __super::PreMessageLoop(nShowCmd); 
                  if   (hr   ==   S_FALSE)   hr   =   S_OK;   //要这句才能走下去 
                  pWork=new   CWorkThread(); 
                  return   hr; 
          } 
          HRESULT   RegisterAppId(bool   bService   =   false)   throw() 
          {                       
                  HRESULT   hr   =   S_OK; 
                  BOOL   res   =   __super::RegisterAppId(bService);   
                  if   (bService) 
                  { 
                            if   (IsInstalled()) 
                            {                 
                                      SC_HANDLE   hSCM   =   ::OpenSCManagerW(NULL,   NULL,   SERVICE_CHANGE_CONFIG); 
                                      SC_HANDLE   hService   =   NULL; 
                                      if   (hSCM   ==   NULL) 
                                              hr   =   AtlHresultFromLastError(); 
                                      else 
                                      { 
                                              hService   =   ::OpenServiceW(hSCM,   m_szServiceName,   SERVICE_CHANGE_CONFIG); 
                                              if   (hService   !=   NULL) 
                                              { 
                                                        const   int   m_szServiceNameLen   =   4096; 
                                                        const   int   m_szServiceDescriptionLen   =   2000; 
                                                        WCHAR   m_szServiceDescription[m_szServiceDescriptionLen]=L "你的服务描述 "; 
                                                        SERVICE_DESCRIPTION   sdBuf   =   {m_szServiceDescription}; 
                                                        res   =   ChangeServiceConfig2W(hService,   SERVICE_CONFIG_DESCRIPTION,   &sdBuf); 
                                                        ::CloseServiceHandle(hService); 
                                              } 
                                              else 
                                                        hr   =   AtlHresultFromLastError(); 
                                              ::CloseServiceHandle(hSCM); 
                                      } 
  
                            } 
                  } 
                  return   hr; 
          } 
}; 
  
CNVSStoreServerModule   _AtlModule; 
  
extern   "C "   int   WINAPI   _tWinMain(HINSTANCE   /*hInstance*/,   HINSTANCE   /*hPrevInstance*/,   
                                                                          LPTSTR   /*lpCmdLine*/,   int   nShowCmd) 

          return   _AtlModule.WinMain(nShowCmd); 
}


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


posts - 12, comments - 0, trackbacks - 0, articles - 1

Copyright © 黄超