代码改变世界

Windows Service结合调试+相关资料 之我见

2011-07-19 11:01  沐海  阅读(1503)  评论(4编辑  收藏  举报

Windows Service 需要3种程序:

服务程序

服务控制程序

服务配置程序

————————————————————

服务程序

服务程序需要3个部分:

主函数

service-main函数

处理程序

有关一个SCM(服务控制管理器)。可以把启动或停止服务的请求发给服务

——————————————————

SCM怎么与服务通信?

SCM发送启动服务请求给服务。 调用服务进程的主函数.服务发回SCM。scm为每一个服务都注册一个service-main函数。

主函数是服务程序的入口点。在这里service-main函数的入口点必须用SCM注册。

从主函数入口进入到service-main函数的入口。然后调用 来注册处理程序。然后SCM调用处理程序的启动。

——————————————————————————————————————

主函数

服务的主函数是程序的一般入口点。即Main()方法,它可以注册多个service-main函数

——————————————————

service-main函数

包含服务的实际功能。服务必须为所提供的每个服务注册一个service-main函数。

服务程序中可以在一个程序中提供许多服务。

SCM现在为每一个应该启动的服务调用service-main函数。

service-main函数的一个重要任务就是 注册一个处理程序。

——————————————————————————

处理程序

必须响应来自SCM的事件。服务可以停止、暂停、重新开始、。处理程序必须响应这些事件。

————————————————————

服务控制程序:可以控制服务,把控制代码发送给服务。处理程序应该响应这些事件。

服务配置程序:服务必须在注册表中配置。启动类型。用户和依赖关系。

Window 服务的类。

System.ServiceProcess名称空间中 实现服务的3部分的服务类。

服务程序====ServiceBase类

服务控制程序===ServiceController类

安装和配置类====ServiceProcessInstaller类和 ServiceInstaller类

(一一对应关系)

____________________(下面主要讲一下 关于 Windows服务需要的3中程序 之一   Windows服务程序)____________

Windows服务程序:

是一个没有屏幕的程序。所以VS设计器中并没有一些控件。

————————————————

1.服务程序类中 -- 设计器中---  属性  --ServiceName =======对应的就是 管理工具--服务 中显示的 注册表中的服务的名称 

还可以在 InitalizeComponent()方法中设置 ServiceBase的派生类的值。

『     private void InitializeComponent()
        {
            components = new System.ComponentModel.Container();
            this.ServiceName = "s";//这里设置了。前台设计器中的属性值也随之改变。  但必须要在初始化组件这个函数中才能对属性进行改变。
        }

 这个名称和下面对应

 2. private System.ServiceProcess.ServiceInstaller serviceInstaller1;//被安装执行文件调用的实现的服务的类的实例

this.serviceInstaller1.ServiceName = "Services";//指向服务名称

首先由服务程序类来指定对应的 服务名称。然后再使用时,对应的服务都要对应 此服务程序类中设置的服务名称。

如果出现服务重名,已存在问题:

改变服务程序类对应的 服务名称。再改变,ServiceInstaller (服务安装类对象)指向的服务名称,即可。

——————————

Windows服务程序 在上面我们简单介绍过了。下面我再详细介绍一下。

上面说:

服务程序需要3个部分:

主函数

service-main函数

处理程序

这里 具体实现时。对应的3个部分和各个步骤。我进行详细的描述

----------------

ServiceBase类

是所有用.NET Framework 开发的Windows服务 的基类。

前面用到的Windows 服务程序就是派生自 此类。

Windows 服务程序类 中使用一个未归档的辅助类System.ServiceProcess.NativeMethods与SCM进行通信。

System.ServiceProcess.NativeMethods类是Win32API调用的包装类。ServiceBase类是内部的。因此不能在这里的代码中使用它。

当在服务应用程序中定义服务类时从 ServiceBase 派生。任何有用的服务均将重写 OnStart 和 OnStop 方法。
对于其他功能,可以用特定行为重写 OnPause 和 OnContinue 来响应服务状态的更改。

服务是长时间运行的可执行文件,它不支持用户界面,在登录的用户帐户下可能无法运行。服务可以在没有任何用户登录计算机的情况下运行。

默认情况下,服务在“系统”帐户下运行,该帐户与“管理员”帐户不同。不能更改“系统”帐户的权限。
或者,可以使用 ServiceProcessInstaller 指定运行服务时将使用的用户帐户。

一个可执行文件可以包含多项服务,但对每项服务均必须包含一个单独的 ServiceInstaller。ServiceInstaller 实例在系统中注册服务。
安装程序还将每项服务与一个事件日志关联,您可以使用该日志记录服务命令。可执行文件中的 main() 函数定义哪些服务应该运行。
服务的当前工作目录是系统目录,而不是可执行文件所位于的目录。

当启动某项服务时,系统将定位相应的可执行文件,并运行该服务的 OnStart 方法(它包含在可执行文件内)。但是,运行服务与运行可执行文件并不相同。
可执行文件仅加载服务。服务则通过“服务控制管理器”访问(例如启动和停止)。

当您对服务首次调用“开始”时,可执行文件调用 ServiceBase 派生类的构造函数。在构造函数执行之后将立即调用 OnStart 命令处理方法。
在服务首次加载之后,构造函数不会再次执行,因此有必要将构造函数执行的处理和 OnStart 执行的处理分开。
可以由 OnStop 释放的任何资源都应在 OnStart 中创建。如果服务在 OnStop 释放资源后再次启动,那么,在构造函数中创建资源会妨碍这些资源的正确创建。

“服务控制管理器”(SCM) 提供与服务交互的方式。可以使用 SCM 将“开始”(Start)、“停止”(Stop)、“暂停”(Pause)、“继续”(Continue) 
或自定义命令传递到服务中。SCM 使用 CanStop 和 CanPauseAndContinue 的值,决定服务是否接受“停止”、“暂停”或“继续”命令。
仅当服务类中相应的属性 CanStop 或 CanPauseAndContinue 为 true 时,才会在 SCM 的上下文菜单中启用“停止”、“暂停”或“继续”。
如果已启用,则相应的命令将传递到服务,并且调用 OnStop、OnPause 或 OnContinue。如果 CanStop、CanShutdown 或 CanPauseAndContinue 为 false,
则即使已实现相应的命令处理方法(如 OnStop),也不会予以处理。

可以使用 ServiceController 类通过编程实现 SCM 使用用户界面实现的功能。
可以自动处理控制台中可用的任务。如果 CanStop、CanShutdown 或 CanPauseAndContinue 为 true,但尚未实现相应的命令处理方法(如 OnStop),
则系统引发异常并忽略该命令。

不必在 ServiceBase 中实现 OnStart、OnStop 或其他任何方法。然而,服务的行为在 OnStart 中加以描述,因此至少应重写该成员。
可执行文件的 main() 函数通过调用 Run 方法,在服务控制管理器中注册可执行文件中的服务。
传递给 Run 方法的 ServiceBase 对象的 ServiceName 属性必须与该服务的服务安装程序的 ServiceName 属性匹配。

可以使用 InstallUtil.exe 在系统中安装服务。
 

SCM、windows服务程序类、System.ServiceProcess名称空间中的类是怎么样相互作用的。

他们的作用的时间范围是在  服务的安装之后,首次启动时,调用onStart()方法之前,这些类之间的通信原理;

============================================

SCM这里你可以理解为 管理工具--服务--某个服务 --启动。

SCM启动应该启动的服务的进程。首先调用Main()方法。在服务的主要入口。然后调用Run()方法。

namespace WindowsService1
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        static void Main()
        {
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[] 
			{ 
				new Service1() 
			};
            ServiceBase.Run(ServicesToRun);
        }
    }
}

Run()方法是用SCM中的NativeMethods.StartServiceCtrlDispatcher()方法  来 注册 ServiceMainCallBack()方法,并把记录写到事件日志中。

然后SCM调用已经注册的ServiceMainCallBack()方法。ServiceMainCallBack()本身使用NativeMethods.RegisterServiceCtrlHandler[EX]()方法在

SCM中注册处理程序。并在SCM中设置服务状态。

处理程序是在ServiceCommandCallBack()方法中执行的。

ServiceCommandCallBack()方法再把请求发送给OnStart()方法(即:调用OnStart()方法)。

在OnStart()方法中实现启动代码。如果OnStart()方法执行成功。就把字符串“Service Started Sucessful”写到事件日志中。

处理程序是在ServiceCommandCallBack()方法中执行的。

当改变了对服务的请求时。SCM就调用ServiceCommandCallBack()方法。

ServiceCommandCallBack()方法再把请求发送给OnStop()等方法。

++++++++++++++++++++
主函数

ServiceBase类的数组  

ServiceBase[] ServicesToRun;

  ServicesToRun = new ServiceBase[]
   {
    new Service1()
   };

  ServiceBase.Run(ServicesToRun);

如果这个服务进程中要运行多个服务。就需要把具体服务类的多个实例添加到数组中。

然后把数组传给 静态方法RUN();

使用RUN()方法,可以把SCM引用(一些处理程序等等。)提供给服务的入口点。  (MAIN---Service-Main)

服务进程的主线程现在处于停滞状态。等待服务的结束。

++++++++++++++++++
服务的启动

OnStart()方法必须返回给调用者(即ServiceBase类中的 ServiceMainCallBack()方法。)

ServiceBase类注册处理程序,并 在调用 OnStart()之前把服务成功启动 的消息通知给SCM。

++++++++++++++++++++++

关于服务的安装、监视、控制。下一篇再讲。

记录生活、工作、学习点滴!
E-Mail:mahaisong@hotmail.com 欢迎大家讨论。
沐海博客园,我有一颗,卓越的心!