创建一个新的服务
2010年11月23日
创建一个新的服务
执行服务的程序也是一个EXE文件,不过它必须符合某些特定的规范,以便可以与SCM进行正确的交互。微软很细致地设计了函数调用的流程,你必须遵循这些流程,否则你的服务就不能工作。具体的规定如下所列。你可以在Win32编程者的参考指南中找到以下涉及的函数,这些资料在SDK的Win32在线帮助或者Visual C++都有:
.服务的代码必须要有一个一般的main或者WinMain函数。这个函数应该会马上调用StartServiceCrtlDispatcher函数。通过调用这个函数,你可以让SCM得到ServiceMain函数的指针,这样在SCM要启动该服务时,就可以调用它
.在SCM要启动服务的时候,就会调用ServiceMain函数。例如,如果管理员在服务管理器中按下启动的按钮,SCM就会在一个独立的线程中执行ServiceMain函数。ServiceMain应该调用RegisterServiceCtrlHandler函数,这样可以注册一个Handler函数,以便SCM对服务进行控制。Handler函数的名字可以是任意的,不过它会在Handler下的文档中列出来。RegisterServiceCtrlHandler函数会返回一个句柄,在服务需要发送状态信息给SCM时,可以通过该句柄进行。
.ServiceMain函数也必须启动做该服务实际工作的线程。在服务停止前,ServiceMain函数是不应该有返回的。当它返回的时候,服务已经停止了。
.Handler函数包含了一个switch语句,用来分析由SCM传送过来的请求。默认的情况,SCM可以发送以下任何的的控制常数:
SERVICE_CONTROL_STOP - 要服务停止
SERVICE_CONTROL_PAUSE - 要服务暂停
SERVICE_CONTROL_CONTINUE - 要服务继续
SERVICE_CONTROL_INTERROGATE - 要服务马上报告它的状态
SERVICE_CONTROL_SHUTDOWN - 告诉服务即将关机
也可以创建自定义的常数(值在128到255之间),并且通过SCM发送给服务。
如果你创建的EXE包括有以上提到的main、ServiceMain和Handler函数,以及执行服务自身任务的线程函数,那么你的服务程序设计就完成了。以下的图总结了这些不同的函数和SCM之间的交互:
****************图一***********************
在本文的最后还有几段程序的列表,其中列表一为我们展示了一个可能是最简单的服务。该服务只发出 "嘟 "的响声。默认的状态下,它每两秒响一次。你可以通过启动的参数来修改发声的间隔。这个服务挺完整,它可以正确响应SCM传来的每个控制信号。因此,这个程序可作为你创建自己服务的一个很好的模板。
main函数通过调用StartServiceCtrlDispatcher来注册ServiceMain函数。注册的操作使用了一个SERVICE_TABLE_ENTRY结构的数组。在这个例子中,该程序只包含了一个服务,因此在表中只会有一个项目。不过,对于一个EXE文件,可以创建几个任务,这样在表中就会有几项,以识别不同的ServiceMain函数。在调用StartServiceCtrlDispatcher之前,可在main函数中放入初始化的代码,不过这些代码必须在少于30秒内完成,否则,SCM会认为某些地方出错而终止服务。
在自动或者手动启动服务时,将会调用ServiceMain函数。ServiceMain函数将包含有以下的步骤:
1.它马上调用RegisterServiceCtrlHandler来注册Handler函数,作为SCM控制该服务的Handler函数
2.然后它将调用SendStatusToSCM函数,将当前的进程通报给SCM。第四个参数是一个“click count”值,在程序每次更新状态时,它的值就会增加。SCM和其它的程序可以根据click count的值来知道初始化期间进行的处理。最后的参数是 "wait hint ",是用来告诉SCM在click count下次更新前,它需要等待的时间(以毫秒计算)。
3.ServiceMain接着会创建一个事情,该事件在函数的底部使用,可让它一直运行,直到SCM发出一个STOP的请求。
4.接着,ServiceMain检查启动的参数。参数可在用户手动启动服务时,通过服务管理工具中的启动参数传送过来。这些参数以一个argv形式的数组进入ServiceMain函数。
5.如果你的服务需要处理其它初始化的任务,它们应该放在这一步,在调用InitService之前。
6.ServiceMain函数接着调用InitService函数,这将启动线程并做服务的真正工作。如果该调用成功,SverviceMain将会通知SCM服务已经成功启动。
7.ServiceMain将调用WaitForSingleObject,用来等待terminateEvent事件对象被设置。这个对象通过Handler函数设置,一旦它被设置,ServiceMain将调用终止的函数来做清除的工作,然后就返回并停止服务。
你从上面可以看到,在这个函数中并没有多少灵活的地方。除了第5步外,你必须按步执行以上提到的任务,否则服务将不可以正确启动。
终止函数清除所有打开的句柄,并且发送一个状态的信息给SCM,告诉它服务现已停止。
在SCM要暂停、继续、询问或者停止服务时,它就会调用Handler函数。要停止服务,Handler设置terminateEvent,这样做会导致ServiceMain(它会以一个独立线程的形式执行)终止并且返回。一旦ServiceMain返回,服务就停止了。
SendStatusToSCM 函数负责发送服务的当前状态给SCM。
在需要启动服务线程时,ServiceMain就会调用InitService函数。该函数调用CreateThread来为服务创建一个新的线程。
ServiceThread函数包含有该服务真正要做的工作。在这个例子中,该线程包含有一个无限的循环,以一个预定义的时间间隔发出响声。在你创建自己的服务时,你可以在该线程中放入任何的代码,调用Win32函数或者你自己的函数。
安装和移除服务
为了使用上面提到的发响声服务,你必须安装它。安装可让SCM知道这个服务,并且让SCM将它加入到控制面板中的服务列表中。表单二的代码展示了如何安装一个服务。
表单2先通过OpenSCManager函数打开一个到SCM的连接。在OpenSCManager的调用中,你必须指定你要做的东西,以便SCM可以验证这个行为。如果你登录的帐号没有足够的权限,该调用将返回NULL。
CreateService的调用是真正用来装入新服务的。它使用OpenSCManager返回至SCM的指针、名字、标签和命令行中的EXE文件,还有一些标准的参数值。使用SERVICE_WIN32_OWN_PROCESS表明该服务的EXE文件只包含有一个服务,而SERVICE_DEMAND_START则表明该服务是手动而不是自动启动的。使用命令行安装程序的一个典型格式如下:
install BeepService "Beeper " c:\winnt\beep.exe
第一个参数是SCM内部使用的服务名字。这个名字也用在以后移除服务。第二个参数是一个标识符,即服务管理中显示的名字。第三个参数指出该服务的执行文件的路径。在你安装服务后,可在控制面板的服务管理中启动它。如果有错,可在Win32 API的在线文档中查出错误代码的含义。
要移除服务,你要按列表3的步骤进行。它首先打开一个到SCM的连接,然后使用OpenService函数打开一个与服务的连接。列表3中接着查询服务来看它是否现已停止了。如果不是的话,就会停止它。DeleteService 用来从控制面板中移除服务,移除操作的典型格式如下:
remove BeepService
需要的话,你也可以在马上重新安装服务。
发表评论
-
QTP的2种脚本调用方法是什么
2012-01-20 02:14 917QTP的2种脚本调用方法是什么 2011年06月14日 ... -
让windows批处理脚本在后台运行
2012-01-20 02:14 703让windows批处理脚本在后台运行 2010年12月24日 ... -
VBS学习笔记(2): Call造成的麻烦
2012-01-20 02:14 592VBS学习笔记(2): Call造成的麻烦 2011年02月 ... -
用vbs实现文本循环读取
2012-01-20 02:14 533用vbs实现文本循环读取 2010年06月16日 因为测 ... -
VBS启动Process
2012-01-20 02:14 592VBS启动Process 2010年06月09日 Run ... -
小学语文毕业知识整理与复习题
2012-01-19 10:04 572小学语文毕业知识整理 ... -
总体上说,是c++ builder胜于VC++,DELPHI是最好
2012-01-19 10:04 764总体上说,是c++ builder胜 ... -
FPS游戏透视源码!
2012-01-19 10:04 2554FPS游戏透视源码! 2011年10月03日 需要的自己 ... -
PE文件格式详解③
2012-01-19 10:03 918PE文件格式详解③ 2010年12月04日 PE可选头部 ... -
android最新的SDK安装方法+ 离线安装方法
2012-01-17 02:45 683android最新的SDK安装方法+ 离线安装方法 2010 ... -
Eclipse+Android SDK+ADT(@XP)搭建时候的几个小问题
2012-01-17 02:45 750Eclipse+Android SDK+ADT(@XP)搭 ... -
Android SDK2.1开发环境的搭建
2012-01-17 02:45 689Android SDK2.1开发环境的搭建 2010年11月 ... -
通过QQ旋风离线下载Android SDK,速度超快
2012-01-17 02:44 747通过QQ旋风离线下载Android SDK,速度超快 201 ... -
Qt 学习笔记 --Qt SDK 的下载安装与配置
2012-01-17 02:44 622Qt 学习笔记 --Qt SDK 的下 ... -
flex各种用法
2012-01-15 22:21 466flex各种用法 2010年02月22日 //获得屏幕的 ... -
Flex开发实例――个人学习心得
2012-01-15 22:21 560Flex开发实例――个人学习心得 2009年10月15日 ... -
Flex 的一些整理
2012-01-15 22:21 559Flex 的一些整理 2010年11月16日 你常用的 ... -
自动根据内容调整列宽advanceddatagrid autoresize
2012-01-15 22:21 811自动根据内容调整列宽advanceddatagrid auto ... -
AdvancedDataGrid的使用,动态插入组列
2012-01-15 22:20 495AdvancedDataGrid的使用,动态插入组列 201 ...
相关推荐
创建一个新服务的监控非常简单,创建一个目录,并且在此目录下写一个名称为'run'的脚本,在这个脚本里定义启动目标服务的命令即可。 4 multilog将错误信息保存到一个或多个日志中。It optionally timestamps each ...
构建一个简单的HTTP服务器的C#程序实例。实现响应GET、POST请求。在服务端创建一个tcp通信来负责...每一次监听程序都会创建一个新的TcpClien,HttpServer类又会创建一个新的HttpProcessor,然后启动一个线程来操作。
用C#创建Windows服务(WindowsServices)Windows服务在...第一步:创建服务框架要创建一个新的Windows服务,可以从VisualC#工程中选取Windows服务(WindowsService)选项,给工程一个新文件名,然后点击OK。结果看起来是
用一个简单的例子,介绍如何使用webmin创建一个站点。
详细描述了如何使用vb.net来创建一个新的windows service
api-mock, 在一个API蓝图上,创建一个模拟服务器 api模拟 这个项目已经在积极开发,并且我们正在寻找一个新的维护者。 如果你对帮助感兴趣,请打开一个问题。 API模拟是一个基于的node.js npm MODULE,它从你的API...
此工具可以以最快的速度创建一个属于你自己的FTP服务器,新手一看就懂!运行密码:zengjie
使用Spring4创建一个简单的RESTful Web服务。其中用到了Spring4中的一些新特性,使得创建一个RESTful服务比以往更简单,比如可以不再依然tomcat容器和一大堆的xml配置文件。
在linux服务器16个节点上创建相同名字相同密码的账户,要求是两个输入参数,用户名和密码
如果以debian软件包的形式安装,则会创建一个新服务,并监视映像目录中是否有任何更改并更新json文件。 要求 Python:3.5.2或更高版本。 Nginx的 的OpenSSL 构建debian软件包 制作包装 要构建lxd-image-server,...
gerrit服务器管理的android源码,在现有项目上,创建一个子项目,web和本地的操作过程,及问题解决
好记性不如烂笔头,好笔头不如真例子 创建一个WCF服务程序 Hello World 是对WCF爱好者新手的一个引导
要创建一个新的 Windows 服务,可以从Visual C# 工程中选取 Windows 服务(Windows Service)选项,给工程一个新文件名,然后点击 确定。你可以看到,向导向工程文件中增加WebService1.cs类:其中各属性的含意是:...
在您的 Drupal 实例上安装并启用创建一个新服务(记住 API 端点)。 启用 application/json 和 application/x-www-form-urlencoded 请求解析器启用 json 和 jsonp 作为响应格式化程序启用用户资源(登录、注销、...
创建CF的dns服务器:配置DNS 新创建一个虚拟机,作为dns-server (本文使用已经有的dns服务器,地址:10.106.1.36) (0、安装前,先运行下apt-get update,更新下虚机本地的文件库)
shell自动化脚本,自动判断文件夹(目录)是否存在,如不存在自动创建,可执行,下载可测试
此命令创建了一个用户sam,其中-d和-m选项用来为登录名sam产生一个主目录/usr/sam(/usr为默认的用户主目录所在的父目录)。 # useradd -s /bin/sh -g group –G adm,root gem 此命令新建了一个用户gem,该...
分步安装打开自动机创建一个新服务添加操作运行 AppleScript 把的内容粘贴进去在Run AppleScript操作上方,有一个选择框:而不是text ,选择No input 使用任意名称保存文件在System Preferences > Keyboard > ...
为医患双方共赢创建未来医疗服务新模式实用.pdf
1.编写带输入参数的存储过程proc_St:在查询分析器中创建一个存储过程,要求输入学号和姓名-----即要求以学号(@SSno)和姓名(@SSname)为存储过程的输入参数(存储过程的参数名必须以@开头,每个参数都应当有数据...