一个建立NT服务的类

作者:Joerg Koenig

翻译:Yuan Wenmao

原文:A Class For Building An NT Service

曾经尝试写一个NT服务吗?

我最近的一个项目需要开发一个CORBA服务,将其运行成NT服务,由于下一个项目也是需要NT服务,我就想花点时间把他做得通用一点给更多的项目使用。成果就是这个CNTService类,通过CodeGurus与大家分享。

通过这个类可以很容易的创建NT服务,所有的困难部分都被这个类完成了,你只需派生出你自己的类并重写”Run()”和”Stop()”两纯虚函数就可以了。当然还有好几个虚函数可以重写。

         这个类接受一组命令行参数。比如说你可以使用-d选项使其按控制台程序运行,这样调试起来就容易多了。

此外这个类还可以安装卸载服务,也是通过命令行参数控制(当然你也可以重定义它)。
 CNTService支持UNICODE和非UNICODE两种编译方式。

建立一个服务

现在让我们亲眼看看如何创建一个自己的服务。

步骤如下(假设你使用的是VC++5.0)

1.       创建一个新的控制台应用程序工程文件。

2.       把NTService文件包放入新工程文件目录中。

3.       将 "NTService.cpp" 和"NTServiceEventLogMsg.mc" 添加到工程中。

4.       打开 Project->Settings ... 对话框并且如下图所示填写。

5.       编译"NTServiceEventLogMsg.mc"文件. 这样会产生 "NTServiceEventLogMsg.h" 和"NTServiceEventLogMsg.rc"两个文件。

6.       将产生的资源文件添加到工程中。

7.       从CNTService类派生出自己的服务类并且重写至少两个方法"Run()"和"Stop()"。

8.       写一个简单的"main()" 函数去启动你程序的功能(你可以使用 sample 工程作为一个好的起点)。

9.       一旦工程编译没有错误了,你就可以立即启动它。这之前你应该打再次打开 Project->Settings ... 对话框,选择 AllConfigurations ,选中工程名字那一行,激活 Debug 标签并在Program arguments:域增加 -d 选项。

现在你可以将你的服务当控制台程序运行并调试了,可以使用Ctrl-C或Ctrl-Break去停止服务(这会模拟一个对SCM(Service Control Manager)的停止请求)。


如何填写文件NTServiceEventLogMsg.mc的配置

现在让我们将服务开启为一个真正的NT服务(假定使用Sample工程)

1.       如果你的账号不属于管理员组,切换为管理员账户登入(这会是有些事情容易点)。

2.       使用 –i选项开启程序. 这样就安装了你的服务。

3.       如果最后一步顺利完成, 你就可以打开控制面板启动 Services程序。查找你的服务的显示名字并选中它(如果你尝试的是sample程序,则显示名字叫Very Simple Service )。

4.       按下 Startup ... 按钮,查看 LogOn As:项,现在可以勾选System Account。如果是sample程序,确保你勾选了 Interact With The Desktop项。这是必需的,因为sample程序使用了MessageBox()函数(这与桌面有关)。如果不勾选此项,sample 不仅不能正确运行还会自动挂起;如此你将不能再次停止服务!只要稍有经验便可增强sample程序,使它在安装此服务的同时便选中此选项,但我想保证sample 程序尽可能的简单,所以这个问题留给你实现。

Sample工程实现了一个非常简单的服务。派生类(声明和实现)和main()函数都包含在同一个文件当中(main.cpp)。这个文件少于100行(去除注释可以确保一页纸就能打印!)

服务只是每10秒弹出一个消息框。

更多信息,参看 CNTService.h- sample工程。我相信这是很好的注释(如果有意见,告知我)。

改变的修订版

·        命令行参数中增加两个切换选项: -e 使运行中的服务停止(类中的相应方法为:virtual BOOL EndService())和-s 如果服务未运行,使服务开启(对应方法:virtual BOOL StartupService())。

·        Todd C. Wilson 增加了对Win95的支持。这使得你可以创建一个像Windows 95程序的服务(所谓的"Faceless Application",无界面应用程序)。就想服务一样, 这样的应用程序会跟随系统自动启动且一个用户注销后仍然存在。 我的经历对此类应用程序作用不大:我可以注销, 在我再次登入前系统是挂起的。 而且 BoundsChecker 5 (是的,我经常使用这个强大的工具测试我的程序)说, 下列语句返回一个无效指针(准确的说应该是“返回的指针未指向一个函数”)

 typedef DWORD (WINAPI *fp_RegServProc)(DWORDdwProcessId,DWORD dwType); 
 fp_RegServProc fncptr=NULL; 
// ... 
HMODULE hModule =::GetModuleHandle(TEXT("kernel32.dll")); 
fncptr=(fp_RegServProc)::GetProcAddress(hModule,"RegisterServiceProcess"); 
if (fncptr!=NULL) 
    (*fncptr)(0, RSP_SIMPLE_SERVICE); 

如果达到最后一句,BoundsChecker 警告说, 指针fncptr 未指向一个函数。然而,sample继续执行未碰到严重的错误。

如果你打算开发一个windows95下的无界面应用程序,就需要注意这个问题。 Sample工程提供了配置项"Win32 Win95 Debug",你可以用来尝试此新特性。

NTService 使用 MFC

微软推荐将NT服务写成控制台应用程序。但是,也有可能将使用MFC写NT服务。 如此,并不需要创建一个MFC向导程序(当然也可以这样做,不过需要移除一些代码,因为通常你不需要文档&视图结构),一个简单的Win32程序就够了。确保你选择了工程中Settings对话框General标签中的Using MFC in a shared DLL项。此外,你还需选择C/C++标签中的Multithreaded DLL / DebugMultithreaded DLLCode Generation 域的 Use run-time Library
如果你使用了预编译头文件,确保不要定义 #define VC_EXTRALEAN,因为基于MFC的服务需要partsof the "rarely used stuff",这个宏会拒绝windows头文件 。

我增加了一个MFC示例新工程MFCService 作为sample服务工作区的一部分。尝试将它作为一个更复杂服务的起点。服务(安装、删除等)操作和上一章所讲一样。

CNTService包含三个文件: 
NTService.h 
NTService.cpp 
NTServiceEventLogMsg.mc 
Download Source 14KB 
Download Sample Project 23KB

注意:NTServiceEventLogMsg.mc 文件为Telic Software International B.V.版权所有。

感谢Telic提供

最后更新时间: February 5, 1999

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章