作者: 周星星
下载本文示例代码
感谢[asp12]和[leoyin]的大力帮助,本附件中的程序只是一个没有任何功能的框架程序,程序本身是一个MFC对话框,也是一个NT服务,可以在进入windows之后,用户登陆之前就开始运行。
服务的名称、显示名称、依赖服务 可以在资源中的String Table中修改,分别对应于IDS_SZSERVICENAME、IDS_SZSERVICEDISPLAYNAME、 IDS_SZDEPENDENCIES;需要注意的是String Table中不可以存放空字符串,所以在没有依赖服务的情况下,我在IDS_SZDEPENDENCIES中放了一个空格;
注册服务和卸载服务只需要在运行时加上命令行参数 -install 和 -remove;为了便于调试,附加了一个参数 -debug,可以不经由NT服务管理器而启动。有关于NT服务的代码皆来自于MSDN。
对于非MFC的对话框程序而言,可以简化很多代码;MFC对话框比non-MFC对话框多处理了一个WM_ENDSESSION消息,否则用户在注销并重新登陆之后,程序将失去响应。这是本程序的重点所在。
在程序开始处使用了SetCurrentDirectory将当前目录设置为了模块所在目录,否则当前目录就是NT服务管理器所在目录,所以调试的时候需要注意,当前目录不是工程所在目录了,而是工程目录下Debug目录,这非常方便。
本程序还增加了系统托盘功能,对于系统托盘,本程序处理了两个特殊情况,一个是系统托盘弹出的菜单在失去焦点时会自动消失,另一个是在Explorer.exe崩溃重建时系统托盘也自动重建。
使用-debug参数运行时跟普通程序一样,省略;运行和停止这个服务可以在NT服务管理器中进行,也可以使用控制台命令net shart/stop,如果你愿意增加一些代码,也可以直接启动。停止这个服务还可以使用系统托盘中的Exit菜单。
NT服务常用于无人职守运行,因此也应该避免用户不小心退出程序,所以本人将最小化按钮和关闭按钮的功能变成了隐藏,恢复显示和退出程序可以使用系统托盘中的菜单。
对于不熟悉NT服务的用户需要注意,因为NT服务会在用户登陆之前就开始运行,因此比如连接远程共享就应该如下处理:
1.将网络通讯的服务名称加到IDS_SZDEPENDENCIES中,这样确保网络通讯服务在次服务之前启动;
2.因为用户还没有登陆,所以没有默认的用户名,所以应该提供用户名和密码去访问远程共享。 当然这些都不是本程序应该说明的事。
很多文章说到要在NT服务程序中显示界面,必须要OpenWindowStation(_T("winsta0")...),但本人没有这样做,这是一个疑问。
最后,为了避免法律纠纷,特此声明:本代码是在业余时间编写,虽曾用于部分商业项目,但所有权不属于任何公司,而本人也不需要任何所有权。
测试平台:win2k pro,VC++6.0 + SP5