Win32 Service的简单封装


前段时间学习Windows程序设计,刚好学到Win32 Service,于是写了两个简单的类:BaseService和ServiceCtrl。虽然功能比较简单,但是也能适用于大多数情况。下面介绍一下简单用法,如果你刚好需要写一些简单的服务程序,这两个类也许能派上用场:

1. BaseServiceBaseService.h



1  
   #ifndef BASE_SERVICE_H
 2  
   #define BASE_SERVICE_H
 3  
   
 
    4class 
    BaseService {
 5public 
   :
 6  
       explicit BaseService(LPCTSTR szServiceName,
 7                 DWORD dwServiceType = 
    SERVICE_WIN32_OWN_PROCESS,
 8                 DWORD dwStartType = 
    SERVICE_AUTO_START);
 9     virtual ~ 
   BaseService() {}
10     bool ParseStandardArgs(int argc, char* 
    argv[]);
11  
       bool IsInstalled();
12  
       bool Install();
13  
       bool Uninstall();
14  
       bool Start();
15private 
   :
16     virtual void Run() = 0 
   ;
17     virtual bool OnInitialize() { return true 
   ; }
18     virtual void 
    OnStop() {}
19     virtual void 
    OnPause() {}
20     virtual void 
    OnContinue() {}
21     virtual void 
    OnInterrogate() {}
22     virtual void 
    OnShutdown() {}
23     virtual void 
    OnUserControl(DWORD dwControl) {}
24  
       ...
25  
   };
26  
   
 
   27 #endif/*BASE_SERVICE_H*/



要实现自己的服务类只需从BaseService继承并且Override相关的virtual函数即可,下面示范一个BeepService类,该服务只是简单地每隔2秒beep一下,为了简单所有代码均放在.h文件中:
BeepService.h



1  
   #ifndef BEEP_SERVICE_H
 2  
   #define BEEP_SERVICE_H
 3  
   
 
    4 #include "BaseService.h" 
   
 
    5  
   
 
    6class BeepService : public 
    BaseService {
 7public 
   :
 8  
       BeepService(LPCTSTR szServiceName)
 9  
           :BaseService(szServiceName)
10         ,m_bPaused(false 
   )
11         ,m_bRunning(false 
   ) {}
12  
   
 
   13     virtual void OnStop() { m_bRunning = false 
   ; }
14     virtual void OnPause() { m_bPaused = true 
   ; }
15     virtual void OnContinue() { m_bPaused = false 
   ; }
16     virtual void 
    Run() {
17         m_bRunning = true 
   ;
18         while 
    (m_bRunning) {
19             if (! 
   m_bPaused)
20                 Beep(800, 800 
   );
21             Sleep(2000 
   );
22  
           }
23  
       }
24private 
   :
25     volatile 
    bool m_bPaused;
26     volatile 
    bool m_bRunning;
27  
   };
28  
   
 
   29 #endif/*BEEP_SERVICE_H*/



通常来说只须要Override上面的4个virtual函数就OK了:
Run()中进行实际的工作,OnStop(),OnPause(),OnContinue()则是为了响应Service Control Manager的控制。
test.cpp



1 #include <windows.h> 
   
 
    2 #include <tchar.h> 
   
 
    3 #include <stdio.h> 
   
 
    4 #include "BeepService.h" 
   
 
    5  
   
 
    6int main(int argc, char * 
   argv[]) {
 7  
   
 
    8     BeepService beepService(_T("BeepService" 
   ));
 9     if (! 
   beepService.ParseStandardArgs(argc, argv)) {
10         if 
    (beepService.IsInstalled()) {
11             if (! 
   beepService.Start())
12                 printf("The service can not run from command line.\n" 
   );
13         } else 
    {
14             printf("The service is not installed, " 
   
 
   15                 "use \"%s -i\" to install.\n", argv[0 
   ]);
16  
           }
17  
       }
18     return 0 
   ;
19 }



假设编译后生成的exe文件为beep.exe,则在命令行中可以如下使用:
(1). beep -i    安装service(安装以后系统运行时会自动启动)
(2). beep -u   卸载service(如果service正在运行,则先停止service再卸载)
BaseServiced 的ParseStandardArgs正是用来解析上述两个命令。

2. ServiceCtrl虽然Windows自带的Service Control Manager可以控制服务程序,但是很多时候我们都需要用代码控制,这就用到ServiceCtrl类,该类的接口如下:
ServiceCtrl.h



1  
   #ifndef SERVICE_CTRL_H
 2  
   #define SERVICE_CTRL_H
 3  
   
 
    4class 
    ServiceCtrl {
 5public 
   :
 6  
       ServiceCtrl(LPCTSTR szServiceName);
 7     ~ 
   ServiceCtrl();
 8  
       bool Start();
 9  
       bool Pause();
10  
       bool Continue();
11  
       bool Stop();
12  
       bool Interrogate();
13  
       bool UserControl(DWORD dwControl);
14     DWORD State() const 
   ;
15  
       ...
16  
   };
17  
   
 
   18 #endif/*SERVICE_CTRL_H*/



接口比较直观没什么好说的,看下面的示例代码:
test.cpp



1 #include <windows.h> 
   
 
    2 #include <tchar.h> 
   
 
    3 #include <stdio.h> 
   
 
    4 #include <exception> 
   
 
    5 #include "BeepService.h" 
   
 
    6 #include "ServiceCtrl.h" 
   
 
    7  
   
 
    8int main(int argc, char * 
   argv[]) {
 9  
   
 
   10     try 
    {
11         ServiceCtrl servCtrl(_T("BeepService" 
   ));
12         if (servCtrl.State() != 
    SERVICE_STOPPED) {
13             printf("Service already started.\n" 
   );
14         } else 
    {
15  
               servCtrl.Start();
16             printf("Start.\n" 
   );
17             Sleep(6000 
   );
18  
               servCtrl.Pause();
19             printf("Pause.\n" 
   );
20             Sleep(6000 
   );
21  
               servCtrl.Continue();
22             printf("Continue.\n" 
   );
23             Sleep(6000 
   );
24  
               servCtrl.Stop();
25             printf("Stop.\n" 
   );
26  
           }
27     } catch (std::exception & 
   e) {
28         printf("%s\n" 
   , e.what());
29  
       }
30     return 0 
   ;
31 }