Win32 Service的简单封装
前段时间学习Windows程序设计,刚好学到Win32 Service,于是写了两个简单的类:BaseService和ServiceCtrl。虽然功能比较简单,但是也能适用于大多数情况。下面介绍一下简单用法,如果你刚好需要写一些简单的服务程序,这两个类也许能派上用场:
1. BaseService
BaseService.h
1 #ifndef BASE_SERVICE_H
2 #define BASE_SERVICE_H
3
4 class BaseService {
5 public :
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();
15 private :
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*/
2 #define BASE_SERVICE_H
3
4 class BaseService {
5 public :
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();
15 private :
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
6 class BeepService : public BaseService {
7 public :
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 }
24 private :
25 volatile bool m_bPaused;
26 volatile bool m_bRunning;
27 };
28
29 #endif/*BEEP_SERVICE_H*/
2 #define BEEP_SERVICE_H
3
4 #include "BaseService.h"
5
6 class BeepService : public BaseService {
7 public :
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 }
24 private :
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
6 int 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 }
2 #include <tchar.h>
3 #include <stdio.h>
4 #include "BeepService.h"
5
6 int 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
4 class ServiceCtrl {
5 public :
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*/
2 #define SERVICE_CTRL_H
3
4 class ServiceCtrl {
5 public :
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
8 int 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 }
2 #include <tchar.h>
3 #include <stdio.h>
4 #include <exception>
5 #include "BeepService.h"
6 #include "ServiceCtrl.h"
7
8 int 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 }
源代码:点击下载
我最擅长从零开始创造世界,所以从来不怕失败,它最多也就让我一无所有。