代码改变世界

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

  沐海  阅读(1508)  评论(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()方法。

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。

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

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

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述
记录生活、工作、学习点滴!
E-Mail:mahaisong@hotmail.com 欢迎大家讨论。
沐海博客园,我有一颗,卓越的心!
点击右上角即可分享
微信分享提示