65.9K
CodeProject 正在变化。 阅读更多。
Home

Cinchoo - 简化的 Windows 服务开发

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.78/5 (6投票s)

2014年10月27日

CPOL

29分钟阅读

viewsIcon

19857

downloadIcon

132

易于创建和使用的 Windows 服务,自安装、多实例等

目录

1. 引言

Cinchoo 是 .NET 的应用程序框架。它为用户提供的核心功能之一是应用程序配置管理。应用程序配置是在运行时应用程序从源读取和/或写入的信息。

它为开发社区提供的另一个重要功能是统一的、通用的应用程序主机,用于以不同模式构建和运行应用程序。一次编写,应用程序即可作为控制台、Windows、WPF、Windows 服务或 Windows 托盘应用程序运行。

在本文中,我将演示如何使用此库来创建 Windows 服务应用程序。 它是一个更简单、更流畅的模型,可以在一个地方配置服务的全部内容。更有说服力的是,您仍然可以将应用程序作为简单的控制台应用程序执行,从而能够进行单步调试,而无需像服务那样跳来跳去。 将其作为库,让您可以专注于核心开发任务。 Cinchoo 提供了一个干净易用的 API 来开发和运行 Windows 服务应用程序。它允许您

  1. 自安装服务应用程序
  2. 安装和运行多实例服务
  3. 能够作为控制台应用程序运行,方便调试
  4. 通过 命令行 传递服务参数
  5. 参数会被保存并在服务自动启动时使用

2. 要求

应用程序主机库是用 C# 编写的,用于 .NET 4.0 Framework。它是 Cinchoo 框架的一部分,Cinchoo 是一个功能丰富的出色库,具有配置管理、通用应用程序主机、Shell 功能等。

3. “Hello World!” 示例

让我们从一个简单的 Windows 服务应用程序示例开始,该示例将“Hello World!”消息打印到日志文件中。

在此处下载最新的 Cinchoo 二进制文件 此处。(Nuget 命令: Install-Package Cinchoo)

  • 打开 VS.NET 2010 或更高版本
  • 创建一个示例 VS.NET (.NET Framework 4) 控制台应用程序项目
  • 添加对 Cinchoo.Core.dll 的引用
  • 使用 Cinchoo.Core 命名空间
  • 复制并粘贴以下应用程序主机对象

列表 3.1 定义 ApplicationHost 对象

[ChoApplicationHost]
public class HelloWorldAppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        ChoProfile.WriteLine("Hello world!");
        base.OnStart(args);
    }
}

上面的代码说明了如何定义 ApplicationHost 对象。首先,从 ChoApplicationHost 定义一个 ApplicationHost(例如 HelloWorldAppHost )类,它表示该对象是 ApplicationHost 对象。并且,它必须用 ChoApplicationHostAttribute 装饰才能完成定义。在此示例中,我们覆盖了 OnStart 方法,将“Hello World!”消息打印到日志文件中。

列表 3.2 Main 方法

class Program
{
    static void Main(string[] args)
    {
        ChoApplication.Run(args);
    }
}

我们首先在应用程序的主入口调用 ChoApplication.Run() 方法。 就是这样。所有安装、将应用程序作为服务运行的繁重工作都由库在后台完成。现在您的应用程序是一个启用了服务的应用程序。它也可以作为控制台应用程序运行,以便于调试服务应用程序。

以下是安装、卸载、启动和停止服务的步骤

列表 3.3 安装 HelloWorld.exe 服务

>HelloWorld.exe /@I
HelloWorld [Version 1.0.0.0]
Copyright c  2014

[SC] CreateService SUCCESS

[SC] ChangeServiceConfig SUCCESS

列表 3.4 启动 HelloWorld.exe 服务

>HelloWorld.exe /@S
HelloWorld [Version 1.0.0.0]
Copyright c  2014

列表 3.5 停止 HelloWorld.exe 服务

>HelloWorld.exe /@T
HelloWorld [Version 1.0.0.0]
Copyright c  2014

列表 3.6 卸载 HelloWorld.exe 服务

>HelloWorld.exe /@I
HelloWorld [Version 1.0.0.0]
Copyright c  2014

[SC] DeleteService SUCCESS

列表 3.7 带有 /@? 参数的 HelloWorld.exe

C:\Personal\WindowsService.Test\HelloWorld\bin\Debug>HelloWorld.exe /@?
HelloWorld [Version 1.0.0.0]
Copyright c  2014

HELLOWORLD [/@SN:<string>] [/@SD:<string>] [/@I] [/@U] [/@S] [/@T] [/@P] [/@C] [
/@E:<int>] [/@SP:<string>]

        /@SN    Service Name.
        /@SD    Service Description.
        /@I     Install Service.
        /@U     Uninstall Service.
        /@S     Start Service.
        /@T     Stop Service.
        /@P     Pause Service.
        /@C     Continue Service.
        /@E     Execute Command.
        /@SP    Command Line Parameters.

'@?' 参数将打印出 HelloWorld 应用程序接受的服务级别参数。

列表 3.8 使用 'Test1' 名称安装 HelloWorld.exe 服务

>HelloWorld.exe /@I /@SN:Test1
HelloWorld [Version 1.0.0.0]
Copyright c  2014

[SC] DeleteService SUCCESS

列表 3.9 将 HelloWorld.exe 作为控制台应用程序运行

>HelloWorld.exe
HelloWorld [Version 1.0.0.0]
Copyright c  2014

        Hello world!

4. 定义应用程序主机对象

4.1 ChoApplicationHostAttribute

所有应用程序主机对象都必须由 ChoApplicationHostAttribute 装饰。一个应用程序至少必须定义一个应用程序主机对象。Cinchoo 框架将在应用程序启动时发现它们。

4.2 ChoApplicationHost

所有应用程序主机对象都必须派生自 ChoApplicationHost 类。在其中覆盖必要的覆盖。应用程序必须在入口程序集或引用的程序集中定义一个应用程序主机对象。在此对象中,您可以根据需要覆盖多个方法。

4.2.1 OnStart() 方法

在派生类中实现时,当服务控制管理器 (SCM) 向服务发送 Start 命令时,或者当操作系统启动时(对于自动启动的服务),或者当应用程序传递了'/@S'开关,或者当应用程序以控制台应用程序启动时,都会执行此方法。

使用 OnStart 指定服务收到 Start 命令时要执行的处理。OnStart 是您指定服务行为的方法。OnStart 可以接受参数作为传递数据的方式。

不要使用构造函数执行应在 OnStart 中执行的处理。使用 OnStart 来处理服务的全部初始化。构造函数在应用程序可执行文件运行时调用,而不是在服务运行时调用。可执行文件在 OnStart 之前运行。例如,当您继续运行时,构造函数不会再次调用,因为 SCM 已经在内存中持有该对象。如果 OnStop 释放的资源是在构造函数中分配的而不是在 OnStart 中分配的,那么第二次调用服务时,所需的资源将不会再次创建。

在 OnStart 方法中处理服务的初始化参数,而不是在 Main 方法中。args 参数数组中的参数可以在服务控制台的服务属性窗口中手动设置,也可以通过'/@SP'开关的命令行参数传递。

4.2.2 OnStop() 方法

在派生类中实现时,当服务控制管理器 (SCM) 向服务发送 Stop 命令时,或者当应用程序传递了'/@T'开关时执行。指定服务停止运行时要采取的操作。在派生类中实现时,当服务控制管理器 (SCM) 向服务发送 Stop 命令时执行。指定服务停止运行时要采取的操作。

当 SCM 收到 Stop 命令时,它会使用ChoServiceInstallerSettings.CanStop的值来验证服务是否接受 Stop 命令。如果 ChoServiceInstallerSettings.CanStop 为 true,则将 Stop 命令传递给服务,如果已定义 OnStop 方法,则调用它。如果服务中未实现 OnStop,则 SCM 处理 Stop 命令。 如果 ChoServiceInstallerSettings.CanStop 为 false,则 SCM 会忽略 Stop 命令。 

4.2.3 OnContinue() 方法

在派生类中实现时,当服务控制管理器 (SCM) 向服务发送 Continue 命令时,或者当应用程序传递了'/@C'开关时,OnContinue 运行。指定服务在暂停后恢复正常功能时要采取的操作。

实现 OnContinue 以反映应用程序对 OnPause 的响应。当您继续服务(通过服务控制台或以编程方式)时,将运行 OnContinue 处理,服务将再次变为活动状态。

ChoServiceInstallerSettings.CanPauseAndContinue 属性为 true 时,应重写 OnContinue。如果ChoServiceInstallerSettings.CanPauseAndContinue 为 false,则 SCM 不会将 Pause 或 Continue 请求传递给服务,因此即使实现了 OnPause 和 OnContinue 方法,它们也不会被调用。在 SCM 中,当ChoServiceInstallerSettings.CanPauseAndContinue 为 false 时,Pause 和 Continue 控件将禁用。

4.2.4 OnPause() 方法

在派生类中实现时,当服务控制管理器 (SCM) 向服务发送 Pause 命令时,或者当应用程序传递了'/@P'开关时执行。指定服务暂停时要采取的操作。

使用 OnPause 指定服务收到 Pause 命令时要执行的处理。当ChoServiceInstallerSettings.CanPauseAndContinue 属性为 true 时,应重写 OnPause。 当您继续暂停的服务(通过服务控制台或以编程方式通过 '/@P' 开关)时,将运行 OnContinue 处理,服务将再次变为活动状态。

发送 Pause 请求给服务可以节省系统资源,因为 Pause 不需要释放所有系统资源。例如,如果进程已打开线程,则暂停服务而不是停止它可能允许线程保持打开状态,从而无需在服务继续时重新分配它们。如果您将 Pause 定义为释放所有系统资源,那么它的行为就像 Stop 命令一样。

ChoServiceInstallerSettings.CanPauseAndContinue 设置为 true,并重写 OnPause 和 OnContinue 以指定 SCM 将 Pause 或 Continue 请求传递给您的服务时应执行的处理。OnContinue 应实现为撤销 OnPause 中的处理。

如果 ChoServiceInstallerSettings.CanPauseAndContinue 为 false,则 SCM 不会将 Pause 或 Continue 请求传递给服务,因此即使实现了 OnPause 和 OnContinue 方法,它们也不会被调用。在 SCM 中,当 ChoServiceInstallerSettings.CanPauseAndContinue 为 false 时,Pause 和 Continue 控件将禁用。

4.2.5 OnPowerEvent() 方法

在派生类中实现时,当计算机的电源状态发生变化时执行。这适用于笔记本电脑进入挂起模式时,这与系统关机不同。

使用 OnPowerEvent 指定当 System.ServiceProcess.PowerBroadcastStatus 枚举中指示的系统事件发生时(例如,当计算机进入挂起模式或指示电池电量低时)要执行的处理。

ChoServiceInstallerSettings.CanHandlePowerEvent 属性为 true 时,应重写 OnPowerEvent。

4.2.6 OnShutdown() 方法

在派生类中实现时,当系统正在关机时执行。指定在系统关机前立即应发生的操作。

使用 OnShutdown 指定系统关机时要执行的处理。 此事件仅在操作系统关机时发生,而不是在计算机断电时发生。 当ChoServiceInstallerSettings.CanShutdown 属性为 true 时,应重写 OnShutdown。

4.2.7 OnCustomCommand() 方法

在派生类中实现时,当服务控制管理器 (SCM) 向服务传递自定义命令时,或者当应用程序传递了'/@E'开关时,OnCustomCommand 会执行。指定当具有指定参数值的命令发生时要采取的操作。

OnCustomCommand 允许您指定除了启动、停止、暂停和继续服务之外的其他功能。 SCM 不会检查自定义命令以验证服务是否支持传递的命令参数。它直接将自定义命令传递给服务。如果服务不识别命令参数,则什么也不做。 

自定义命令由 ServiceController 组件中的 ExecuteCommand 语句引发,或者通过'/@E'命令行开关传递命令。使用 switch 语句或 if..then 条件来处理您在服务中定义的自定义命令。 您可以在应用程序中定义或在 OnCustomCommand 中使用的自定义命令的唯一值是 128 到 255 之间的整数。低于 128 的整数对应于系统保留值。

如果ChoServiceInstallerSettings.AutoLog 属性为 true,则自定义命令(像所有其他命令一样)会将条目写入事件日志,报告方法执行是否成功或失败。

4.2.8 OnSessionChange() 方法

从终端服务器会话接收到更改事件时执行。 您必须将ChoServiceInstallerSettings.CanHandleSessionChangeEvent 属性设置为 true 才能启用此方法的执行。

4.2.9 RequestAdditionalTime() 方法

请求为挂起的操作分配额外时间。 RequestAdditionalTime 方法旨在由重写的 OnContinue、OnPause、OnStart 或 OnStop 方法调用,以请求挂起操作的额外时间,从而防止服务控制管理器 (SCM) 将服务标记为无响应。如果挂起的操作不是继续、暂停、开始或停止,则会抛出 InvalidOperationException。

4.2.10 ApplyGlobalApplicationSettingsOverrides() 方法

在派生类中实现时,当框架初始化时,ApplyGlobalApplicationSettingsOverrides 会执行。在这里,您可以覆盖ChoGlobalApplicationSettings 成员。

4.2.11 ApplyAppFrxSettingsOverrides() 方法

在派生类中实现时,ApplyAppFrxSettingsOverrides 在框架初始化时执行。在这里,您可以覆盖ChoAppFrxSettings 成员。

4.2.12 ApplyMetaDataFilePathSettingsOverrides() 方法

在派生类中实现时,ApplyMetaDataFilePathSettingsOverrides 在框架初始化时执行。在这里,您可以覆盖ChoMetaDataFilePathSettings 成员。

4.2.13 BeforeInstall() 方法

在派生类中实现时,BeforeInstall() 方法在服务安装发生之前执行。请注意,此操作仅在服务正在安装时执行。

4.2.14 AfterInstall() 方法

在派生类中实现时,AfterInstall() 方法在服务安装发生之后执行。请注意,此操作仅在服务正在安装时执行。

4.2.15 BeforeUninstall() 方法

在派生类中实现时,BeforeUninstall() 方法在服务卸载发生之前执行。请注意,此操作仅在服务正在卸载时执行。

4.2.16 AfterUninstall() 方法

在派生类中实现时,AfterUninstall() 方法在服务卸载发生之后执行。请注意,此操作仅在服务正在卸载时执行。

5. 管理服务

使用 Cinchoo 框架开发 Windows 服务应用程序通过命令行参数提供了许多选项来自我安装、执行和控制服务应用程序。

5.1 安装服务

如果您使用 .NET Framework 开发 Windows 服务,通常会使用名为 InstallUtil.exe 的命令行实用程序来安装服务应用程序。在使用 Cinchoo 框架进行服务开发时,您不再需要此实用程序。这些服务是自安装的。

5.1.1 安装单实例服务

默认情况下,使用 Cinchoo 框架开发的服务应用程序是单实例服务应用程序。这意味着您最多可以同时安装和运行它的一个实例。通过将'/@I'命令行参数传递给服务可执行文件,将以可执行文件名称作为服务名称来安装服务。对于下面的示例,*'HelloWorld'*服务将被安装在您的机器上。

列表 5.1.1.1 安装服务

>HelloWorld.exe /@I
HelloWorld [Version 1.0.0.0]
Copyright c  2014

[SC] CreateService SUCCESS

[SC] ChangeServiceConfig SUCCESS

5.1.2 安装多实例服务

有时您可能希望安装具有不同名称的多个服务。您可以通过在ChoGlobalApplicationSettings 类中关闭*'SingleInstanceApp'*标志来实现。请访问以下 URL,了解如何在应用程序中关闭此选项。

Cinchoo – 允许多实例应用程序

下面的示例展示了如何使用'/@SN'命令行开关安装一个名为*'TestService'*的服务。

列表 5.1.2.1 安装 'TestService' 服务

>HelloWorld.exe /@I /@SN:TestService
HelloWorld [Version 1.0.0.0]
Copyright c  2014

[SC] CreateService SUCCESS

[SC] ChangeServiceConfig SUCCESS

5.1.2 卸载服务

要卸载服务,您必须使用'/@U'命令行开关。下面的示例展示了如何卸载服务。

列表 5.1.2.1 卸载服务

>HelloWorld.exe /@U
HelloWorld [Version 1.0.0.0]
Copyright c  2014

[SC] DeleteService SUCCESS

列表 5.1.2.2 卸载 'TestService' 服务

>HelloWorld.exe /@U /@SN:TestService
HelloWorld [Version 1.0.0.0]
Copyright c  2014

[SC] DeleteService SUCCESS

5.1.3 启动服务

要启动服务,您必须使用'/@S'命令行开关。下面的示例展示了如何启动服务。

列表 5.1.3.1 启动服务

>HelloWorld.exe /@S
HelloWorld [Version 1.0.0.0]
Copyright c  2014

[SC] DeleteService SUCCESS

列表 5.1.3.2 启动 'TestService' 服务

>HelloWorld.exe /@S /@SN:TestService
HelloWorld [Version 1.0.0.0]
Copyright c  2014

5.1.3 停止服务

要停止服务,您必须使用'/@T'命令行开关。SCM 使用ChoServiceInstallerSettings.CanStop的值来验证服务是否接受 Stop 命令。如果 ChoServiceInstallerSettings.CanStop 为 true,则将 Stop 命令传递给服务,如果已定义 OnStop 方法,则调用它。如果服务中未实现 OnStop,则 SCM 处理 Stop 命令。 如果 ChoServiceInstallerSettings.CanStop 为 false,则 SCM 会忽略 Stop 命令。 

下面的示例展示了如何停止服务。

列表 5.1.3.1 停止服务

>HelloWorld.exe /@S
HelloWorld [Version 1.0.0.0]
Copyright c  2014

[SC] DeleteService SUCCESS

列表 5.1.3.2 停止 'TestService' 服务

>HelloWorld.exe /@S /@SN:TestService
HelloWorld [Version 1.0.0.0]
Copyright c  2014

5.1.4 继续服务

要继续服务,您必须使用'/@C'命令行开关。

SCM 使用ChoServiceInstallerSettings.CanPauseAndContinue 的值来验证服务是否接受 Continue 命令。如果 ChoServiceInstallerSettings.CanPauseAndContinue 为 true,则将 Continue 命令传递给服务,如果已定义 OnContinue 方法,则调用它。如果服务中未实现 OnContinue,则 SCM 处理 Continue 命令。 如果 ChoServiceInstallerSettings.CanPauseAndContinue 为 false,则 SCM 会忽略 Continue 命令。 

下面的示例展示了如何继续服务。

列表 5.1.4.1 继续服务

>HelloWorld.exe /@C
HelloWorld [Version 1.0.0.0]
Copyright c  2014

[SC] DeleteService SUCCESS

列表 5.1.4.2 继续 'TestService' 服务

>HelloWorld.exe /@C /@SN:TestService
HelloWorld [Version 1.0.0.0]
Copyright c  2014

5.1.5 暂停服务

要暂停服务,您必须使用'/@P'命令行开关。

SCM 使用ChoServiceInstallerSettings.CanPauseAndContinue 的值来验证服务是否接受 Pause 命令。如果 ChoServiceInstallerSettings.CanPauseAndContinue 为 true,则将 Pause 命令传递给服务,如果已定义 OnPause 方法,则调用它。如果服务中未实现 OnPause,则 SCM 处理 Pause 命令。 如果 ChoServiceInstallerSettings.CanPauseAndContinue 为 false,则 SCM 会忽略 Pause 命令。 

下面的示例展示了如何暂停服务。

列表 5.1.5.1 继续服务

>HelloWorld.exe /@C
HelloWorld [Version 1.0.0.0]
Copyright c  2014

[SC] DeleteService SUCCESS

列表 5.1.5.2 继续 'TestService' 服务

>HelloWorld.exe /@C /@SN:TestService
HelloWorld [Version 1.0.0.0]
Copyright c  2014

5.1.5 执行自定义命令

要执行自定义命令,您必须使用'/@E'命令行开关和命令标识符(整数)。

您可以在应用程序中定义或在 OnCustomCommand 中使用的自定义命令的唯一值是 128 到 255 之间的整数。低于 128 的整数对应于系统保留值。

下面的示例展示了如何暂停服务。

列表 5.1.5.1 执行自定义命令

>HelloWorld.exe /@E:230
HelloWorld [Version 1.0.0.0]
Copyright c  2014

[SC] DeleteService SUCCESS

列表 5.1.5.2 在 'TestService' 服务上执行自定义命令

>HelloWorld.exe /@E:230 /@SN:TestService
HelloWorld [Version 1.0.0.0]
Copyright c  2014

5.1.6 服务参数

当然,每个应用程序有时都需要一些参数来初始化进程。Windows 服务也不例外。您可以为服务定义两种不同类型的参数

  • 永久
  • 一次性

可以使用'/@SP'命令行开关将参数传递给服务。这些参数会自动传递给 OnStart() 方法。

安装服务时传递的参数将永久保存在注册表中。所有后续运行,SCM 会自动检索这些参数并将其传递给服务的 OnStart()。

列表 5.1.6.1 永久服务参数

>HelloWorld.exe /@I /@SP:"/name:Tom /msg:Hello"
HelloWorld [Version 1.0.0.0]
Copyright c  2014

[SC] CreateService SUCCESS

[SC] ChangeServiceConfig SUCCESS

有时您可能希望在启动服务时覆盖参数。您可以通过多种方式传递参数来实现:

  • 通过在启动服务时通过命令行传递参数
  • args 参数数组中的参数可以在服务控制台的服务属性窗口中手动设置。

在下面的示例中,在启动服务时传递的参数将是一次性参数。

列表 5.1.5.2 一次性服务参数

>HelloWorld.exe /@S /@SP:"/name:Tom /msg:Hello"
HelloWorld [Version 1.0.0.0]
Copyright c  2014

6. 应用程序主机发现

要成功部署您的 Windows 服务应用程序,您必须了解 Cinchoo 框架如何定位和加载构成您应用程序的应用程序主机对象。默认情况下,Cinchoo 框架会尝试从入口程序集定位和加载应用程序主机对象。此默认行为可以通过配置文件设置来覆盖。

Cinchoo 框架在尝试定位应用程序主机对象时会执行一系列步骤。

  1. 检查 App.Cofig/Web.Config 文件
  2. 在入口程序集中定位 ApplicationHost 对象
  3. 定位在引用程序集中找到的第一个 ApplicationHost 对象。

6.1 在 App.Config/Web.Config 文件中检查

Cinchoo 框架会检查应用程序配置文件中有关覆盖应用程序主机对象信息的设置。以下代码提供了一个在应用程序配置文件中指定应用程序主机信息的示例。

列表 6.1.1 App.Config 文件

<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="appFrxSettings" type="Cinchoo.Core.ChoAppFrxSettings, Cinchoo.Core" />
  </configSections>
  <appFrxSettings appEnvironment="" appFrxFilePath="" applicationHostType="HelloWorldApp.TestAppHost, HelloWorld" />
</configuration>

6.2 在入口程序集中定位

当配置文件中未指定类型时,Cinchoo 框架会检查入口程序集中定义的应用程序主机对象。

6.3 定位第一个发现的 ApplicationHost 对象

Cinchoo 框架会扫描所有引用的程序集以查找其中定义的应用程序主机对象,并使用找到的第一个此类对象来管理 Windows 服务。当框架在前一个步骤中未能定位到应用程序主机对象时,将执行此步骤。

7. 自定义

有多种方法可以自定义您的 Windows 服务应用程序,例如服务启动模式、服务标识、自定义安装操作、服务依赖项等。默认设置应该足以满足大多数应用程序的需求,但它们也为您提供了自定义的选项。

自定义可以通过几种方式完成

  • 以编程方式
  • 配置文件

7.1 配置文件

所有可自定义的参数都在Config文件夹下的ChoServiceInstallerSettings.xml文件中定义。

以下是配置文件内容的示例。

列表 7.1.1 ChoServiceInstallerSettings.xml 文件

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceInstallerSettings serviceName="" serviceStartMode="Automatic" depends="" account="LocalSystem" userName="" password="" timeoutInTicks="-1" canHandlePowerEvent="false" canHandleSessionChangeEvent="false" canPauseAndContinue="false" canShutdown="true" canStop="true" autoLog="false" exitCode="0">
    <description />
    <parameters><![CDATA[]]></parameters>
    <recoverySettings resetFailedCounterAfter="0">
      <rebootMessage><![CDATA[]]></rebootMessage>
      <command><![CDATA[]]></command>
      <actions><![CDATA[]]></actions>
    </recoverySettings>
  </serviceInstallerSettings>
</configuration>

7.2 以编程方式

这是以编程方式自定义 Windows 服务应用程序的另一种方式。

以下是样本。

列表 7.1.1 覆盖服务安装程序设置

[ChoApplicationHost]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("OnStart");
        base.OnStart(args);
    }

    protected override void ApplyServiceParametersOverrides(ChoServiceInstallerSettings obj)
    {
        //Customize the parameters
    }
}

8. 配置

一旦将 Cinchoo 框架添加到您的项目以进行服务开发,您就可以通过框架 API 或通过配置文件来配置服务。在本节中,我们将讨论服务使用的最常见的配置参数以及如何通过 API/配置文件来操作它们。

8.1 服务配置

8.1.1 服务名称

指定服务的基名称,因为它在服务控制管理器中注册。此设置是可选的,默认使用入口程序集(可执行文件)名称。

建议服务名称不包含空格或其他空白字符。

列表 8.1.1.1 以编程方式设置 ServiceName

[ChoApplicationHost]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("OnStart");
        base.OnStart(args);
    }

    protected override void ApplyServiceParametersOverrides(ChoServiceInstallerSettings obj)
    {
        obj.ServiceName = "TestService";
    }
}

列表 8.1.1.2 通过 ChoServiceInstallerSettings.xml 文件设置 ServiceName

打开 ChoServiceInstallerSettings.xml 文件,在 'serviceName' 属性中指定服务名称。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceInstallerSettings serviceName="TestService" serviceStartMode="Automatic" depends="" account="LocalSystem" userName="" password="" timeoutInTicks="-1" canHandlePowerEvent="false" canHandleSessionChangeEvent="false" canPauseAndContinue="false" canShutdown="true" canStop="true" autoLog="false" exitCode="0">
    <description />
    <parameters><![CDATA[]]></parameters>
    <recoverySettings resetFailedCounterAfter="0">
      <rebootMessage><![CDATA[]]></rebootMessage>
      <command><![CDATA[]]></command>
      <actions><![CDATA[]]></actions>
    </recoverySettings>
  </serviceInstallerSettings>
</configuration>

列表 8.1.1.3 通过命令行选项设置 ServiceName

>HelloWorld.exe /@I /@SN:TestService

服务名称的优先级顺序如下:

  1. 命令行选项 (/@SN)
  2. 以编程方式
  3. ChoServiceInstallerSettings.xml 文件

系统上的每个服务都必须有一个唯一的名称。如果您需要运行同一服务的多个实例,请在安装服务时考虑使用 InstanceName 命令行选项。

8.1.2 显示名称

在服务控制管理器中指定服务的显示名称。此设置是可选的,默认为服务名称。

列表 8.1.2.1 以编程方式设置 DisplayName

[ChoApplicationHost]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("OnStart");
        base.OnStart(args);
    }

    protected override void ApplyServiceParametersOverrides(ChoServiceInstallerSettings obj)
    {
        obj.DisplayName = "TestServiceDisplayName";
    }
}

列表 8.1.2.2 通过命令行选项设置 DisplayName

>HelloWorld.exe /@I /@DN:TestServiceDisplayName

显示名称的优先级顺序如下:

  1. 命令行选项 (/@DN)
  2. 以编程方式

8.1.3 实例名称

指定服务的实例名称。它与服务名称合并,并用 $ 分隔。此设置是可选的,仅在指定时添加。

列表 8.1.3.1 以编程方式设置 InstanceName

[ChoApplicationHost]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("OnStart");
        base.OnStart(args);
    }

    protected override void ApplyServiceParametersOverrides(ChoServiceInstallerSettings obj)
    {
        obj.InstanceName = "instance1";
    }
}

列表 8.1.3.2 通过命令行选项设置 InstanceName

>HelloWorld.exe /@I /@IN:instance1

显示名称的优先级顺序如下:

  1. 命令行选项 (/@IN)
  2. 以编程方式

此选项通常用于 运行同一服务的多个实例

8.1.4 服务描述

在服务控制管理器中指定服务的描述。此设置是可选的,默认为服务名称。

列表 8.1.4.1 以编程方式设置 ServiceDescription

[ChoApplicationHost]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("OnStart");
        base.OnStart(args);
    }

    protected override void ApplyServiceParametersOverrides(ChoServiceInstallerSettings obj)
    {
        obj.ServiceDescription = "TestService Description";
    }
}

列表 8.1.4.2 通过 ChoServiceInstallerSettings.xml 文件设置 ServiceDescription

打开 ChoServiceInstallerSettings.xml 文件,在 'description' 元素中指定服务描述。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceInstallerSettings serviceName="TestService" serviceStartMode="Automatic" depends="" account="LocalSystem" userName="" password="" timeoutInTicks="-1" canHandlePowerEvent="false" canHandleSessionChangeEvent="false" canPauseAndContinue="false" canShutdown="true" canStop="true" autoLog="false" exitCode="0">
    <description>TestService Description</description>
    <parameters><![CDATA[]]></parameters>
    <recoverySettings resetFailedCounterAfter="0">
      <rebootMessage><![CDATA[]]></rebootMessage>
      <command><![CDATA[]]></command>
      <actions><![CDATA[]]></actions>
    </recoverySettings>
  </serviceInstallerSettings>
</configuration>

列表 8.1.4.3 通过命令行选项设置 ServiceDescription

>HelloWorld.exe /@I /@SD:"TestService Description"

服务描述的优先级顺序如下:

  1. 命令行选项 (/@SD)
  2. 以编程方式
  3. ChoServiceInstallerSettings.xml 文件

8.2 服务启动模式

有多种服务启动模式,每种模式都可以通过配置指定。仅在安装服务时使用此选项。

  1. 延迟自动启动
  2. 自动
  3. 手动
  4. 禁用

列表 8.2.1 通过 ChoServiceInstallerSettings.xml 文件设置 ServiceStartMode

打开 ChoServiceInstallerSettings.xml 文件,在 'serviceStartMode' 属性中指定模式。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceInstallerSettings serviceName="TestService" serviceStartMode="Automatic" depends="" account="LocalSystem" userName="" password="" timeoutInTicks="-1" canHandlePowerEvent="false" canHandleSessionChangeEvent="false" canPauseAndContinue="false" canShutdown="true" canStop="true" autoLog="false" exitCode="0">
    <description>TestService Description</description>
    <parameters><![CDATA[]]></parameters>
    <recoverySettings resetFailedCounterAfter="0">
      <rebootMessage><![CDATA[]]></rebootMessage>
      <command><![CDATA[]]></command>
      <actions><![CDATA[]]></actions>
    </recoverySettings>
  </serviceInstallerSettings>
</configuration>

8.3 服务身份

服务可以配置为作为多种不同身份运行,使用最合适的配置选项。

可能的身份有:

  1. 网络服务
  2. 本地系统(默认)
  3. 本地服务
  4. 用户

8.3.1 网络服务帐户

使用 NETWORK_SERVICE 内置帐户运行服务。网络服务帐户是 SCM 使用的预定义本地帐户。 在网络服务帐户上下文中运行的服务向远程服务器呈现计算机的凭据。您可以按如下方式将服务设置为在此帐户下运行:

列表 8.3.1.1 以编程方式将身份设置为网络服务帐户

[ChoApplicationHost]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("OnStart");
        base.OnStart(args);
    }

    protected override void ApplyServiceParametersOverrides(ChoServiceInstallerSettings obj)
    {
        obj.RunAsNetworkService();
    }
}

列表 8.3.1.2 通过 ChoServiceInstallerSettings.xml 文件将身份设置为网络服务帐户

打开 ChoServiceInstallerSettings.xml 文件,在 'account' 属性中将帐户指定为 'NetworkService'。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceInstallerSettings serviceName="TestService" serviceStartMode="Automatic" depends="" account="NetworkService" userName="" password="" timeoutInTicks="-1" canHandlePowerEvent="false" canHandleSessionChangeEvent="false" canPauseAndContinue="false" canShutdown="true" canStop="true" autoLog="false" exitCode="0">
    <description>TestService Description</description>
    <parameters><![CDATA[]]></parameters>
    <recoverySettings resetFailedCounterAfter="0">
      <rebootMessage><![CDATA[]]></rebootMessage>
      <command><![CDATA[]]></command>
      <actions><![CDATA[]]></actions>
    </recoverySettings>
  </serviceInstallerSettings>
</configuration>

8.3.2 本地系统帐户

使用本地系统帐户运行服务。LocalSystem 帐户是服务控制管理器使用的预定义本地帐户。 它在本地计算机上具有广泛的权限,并在网络上充当计算机。在 LocalSystem 帐户上下文中运行的服务会继承 SCM 的安全上下文。该帐户不与任何已登录的用户帐户关联。它是安装服务时设置的默认帐户。您可以按如下方式显式将服务设置为在此帐户下运行:

列表 8.3.2.1 以编程方式将身份设置为本地系统帐户

[ChoApplicationHost]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("OnStart");
        base.OnStart(args);
    }

    protected override void ApplyServiceParametersOverrides(ChoServiceInstallerSettings obj)
    {
        obj.RunAsLocalSystem();
    }
}

列表 8.3.2.2 通过 ChoServiceInstallerSettings.xml 文件将身份设置为本地系统

打开 ChoServiceInstallerSettings.xml 文件,在 'account' 属性中将帐户指定为 'LocalSystem'。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceInstallerSettings serviceName="TestService" serviceStartMode="Automatic" depends="" account="LocalSystem" userName="" password="" timeoutInTicks="-1" canHandlePowerEvent="false" canHandleSessionChangeEvent="false" canPauseAndContinue="false" canShutdown="true" canStop="true" autoLog="false" exitCode="0">
    <description>TestService Description</description>
    <parameters><![CDATA[]]></parameters>
    <recoverySettings resetFailedCounterAfter="0">
      <rebootMessage><![CDATA[]]></rebootMessage>
      <command><![CDATA[]]></command>
      <actions><![CDATA[]]></actions>
    </recoverySettings>
  </serviceInstallerSettings>
</configuration>

8.3.3 本地服务帐户

使用本地服务帐户运行服务。LocalService 帐户是服务控制管理器使用的预定义本地帐户。 它在本地计算机上具有最低权限,并在网络上呈现匿名凭据。

列表 8.3.3.1 以编程方式将身份设置为本地系统帐户

[ChoApplicationHost]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("OnStart");
        base.OnStart(args);
    }

    protected override void ApplyServiceParametersOverrides(ChoServiceInstallerSettings obj)
    {
        obj.RunAsLocalSystem();
    }
}

列表 8.3.3.2 通过 ChoServiceInstallerSettings.xml 文件将身份设置为本地系统

打开 ChoServiceInstallerSettings.xml 文件,在 'account' 属性中将帐户指定为 'LocalService'。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceInstallerSettings serviceName="TestService" serviceStartMode="Automatic" depends="" account="LocalSystem" userName="" password="" timeoutInTicks="-1" canHandlePowerEvent="false" canHandleSessionChangeEvent="false" canPauseAndContinue="false" canShutdown="true" canStop="true" autoLog="false" exitCode="0">
    <description>TestService Description</description>
    <parameters><![CDATA[]]></parameters>
    <recoverySettings resetFailedCounterAfter="0">
      <rebootMessage><![CDATA[]]></rebootMessage>
      <command><![CDATA[]]></command>
      <actions><![CDATA[]]></actions>
    </recoverySettings>
  </serviceInstallerSettings>
</configuration>

8.3.4 用户帐户

使用指定的用户名和密码运行服务。用户名可以指定为“<domain>\<username>”或 “<username>”。可以配置如下:

列表 8.3.4.1 以编程方式将身份设置为用户帐户

[ChoApplicationHost]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("OnStart");
        base.OnStart(args);
    }

    protected override void ApplyServiceParametersOverrides(ChoServiceInstallerSettings obj)
    {
        obj.RunAsUser("DOMAIN\XBBA123", "passwd");
    }
}

列表 8.3.4.2 通过 ChoServiceInstallerSettings.xml 文件将身份设置为用户帐户

打开 ChoServiceInstallerSettings.xml 文件,在 'account' 属性中将帐户指定为 'User'。然后,在相应的 'userName' 和 'password' 属性中指定用户名和密码。将密码明文保存在配置文件中是不安全的。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceInstallerSettings serviceName="TestService" serviceStartMode="Automatic" depends="" account="User" userName="DOMAIN\XBBA123" password="passwd" timeoutInTicks="-1" canHandlePowerEvent="false" canHandleSessionChangeEvent="false" canPauseAndContinue="false" canShutdown="true" canStop="true" autoLog="false" exitCode="0">
    <description>TestService Description</description>
    <parameters><![CDATA[]]></parameters>
    <recoverySettings resetFailedCounterAfter="0">
      <rebootMessage><![CDATA[]]></rebootMessage>
      <command><![CDATA[]]></command>
      <actions><![CDATA[]]></actions>
    </recoverySettings>
  </serviceInstallerSettings>
</configuration>

8.3.5 提示用户帐户

安装服务时,安装程序会提示输入用于启动服务的用户名/密码组合。用户名可以指定为“<domain>\<username>”或 “<username>”。可以配置如下:

列表 8.3.5.1 以编程方式将身份设置为要提示的用户帐户

[ChoApplicationHost]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("OnStart");
        base.OnStart(args);
    }

    protected override void ApplyServiceParametersOverrides(ChoServiceInstallerSettings obj)
    {
        obj.RunAsPrompt();
    }
}

列表 8.3.5.2 通过 ChoServiceInstallerSettings.xml 文件将身份设置为要提示的用户帐户

打开 ChoServiceInstallerSettings.xml 文件,在 'account' 属性中将帐户指定为 'User'。然后,在相应的 'userName' 和 'password' 属性中留空用户名和密码。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceInstallerSettings serviceName="TestService" serviceStartMode="Automatic" depends="" account="User" userName="" password="" timeoutInTicks="-1" canHandlePowerEvent="false" canHandleSessionChangeEvent="false" canPauseAndContinue="false" canShutdown="true" canStop="true" autoLog="false" exitCode="0">
    <description>TestService Description</description>
    <parameters><![CDATA[]]></parameters>
    <recoverySettings resetFailedCounterAfter="0">
      <rebootMessage><![CDATA[]]></rebootMessage>
      <command><![CDATA[]]></command>
      <actions><![CDATA[]]></actions>
    </recoverySettings>
  </serviceInstallerSettings>
</configuration>

8.4 服务依赖项

指定在此服务启动之前必须启动的服务名称。名称之间用正斜杠 (/) 分隔。 这由 Windows 服务控制管理器管理。

列表 8.4.1 以编程方式设置 Service Depend

[ChoApplicationHost]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("OnStart");
        base.OnStart(args);
    }

    protected override void ApplyServiceParametersOverrides(ChoServiceInstallerSettings obj)
    {
        obj.Depend("MSSQL", "IIS");
    }
}

列表 8.4.2 通过 ChoServiceInstallerSettings.xml 文件设置 Service Depend

打开 ChoServiceInstallerSettings.xml 文件,在 'depends' 属性中指定依赖服务名称。名称必须用斜杠 (/) 分隔。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceInstallerSettings serviceName="TestService" serviceStartMode="Automatic" depends="MSSQL/IIS" account="User" userName="" password="" timeoutInTicks="-1" canHandlePowerEvent="false" canHandleSessionChangeEvent="false" canPauseAndContinue="false" canShutdown="true" canStop="true" autoLog="false" exitCode="0">
    <description>TestService Description</description>
    <parameters><![CDATA[]]></parameters>
    <recoverySettings resetFailedCounterAfter="0">
      <rebootMessage><![CDATA[]]></rebootMessage>
      <command><![CDATA[]]></command>
      <actions><![CDATA[]]></actions>
    </recoverySettings>
  </serviceInstallerSettings>
</configuration>

8.5 高级设置

8.5.1 CanPauseAndContinue

指定服务支持暂停和继续,允许服务控制管理器将暂停和继续命令传递给服务。

当服务暂停时,它会停止正在执行的操作。当您继续服务(通过服务控制管理器或以编程方式)时,OnContinue 会运行。 发送 Pause 请求给服务可以节省系统资源。Pause 不一定释放所有系统资源,但 Stop 会。OnPause 和 OnContinue 通常实现为比 OnStop 和 OnStart 执行更少处理。

当 CanPauseAndContinue 为 true 时,重写 OnPause 和 OnContinue 以指定服务控制管理器 (SCM) 将 Pause 或 Continue 请求传递给您的服务时应执行的处理。OnContinue 应实现为撤销 OnPause 中的处理。

如果 CanPauseAndContinue 为 false,则 SCM 不会将 Pause 或 Continue 请求传递给服务,因此即使实现了 OnPause 和 OnContinue 方法,它们也不会被调用。在 SCM 中,当 CanPauseAndContinue 为 false 时,Pause 和 Continue 控件将禁用。

列表 8.5.1.1 以编程方式设置 CanPauseAndContinue

[ChoApplicationHost]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("OnStart");
        base.OnStart(args);
    }

    protected override void ApplyServiceParametersOverrides(ChoServiceInstallerSettings obj)
    {
        obj.CanPauseAndContinue = true;
    }

    protected override void OnContinue()
    {
    }

    protected override void OnPause()
    {
    }
}

列表 8.5.1.2 通过 ChoServiceInstallerSettings.xml 文件设置 CanPauseAndContinue 

打开 ChoServiceInstallerSettings.xml 文件,在 'canPauseAndContinue' 属性中指定 true/false。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceInstallerSettings serviceName="TestService" serviceStartMode="Automatic" depends="MSSQL/IIS" account="User" userName="" password="" timeoutInTicks="-1" canHandlePowerEvent="false" canHandleSessionChangeEvent="false" canPauseAndContinue="true" canShutdown="true" canStop="true" autoLog="false" exitCode="0">
    <description>TestService Description</description>
    <parameters><![CDATA[]]></parameters>
    <recoverySettings resetFailedCounterAfter="0">
      <rebootMessage><![CDATA[]]></rebootMessage>
      <command><![CDATA[]]></command>
      <actions><![CDATA[]]></actions>
    </recoverySettings>
  </serviceInstallerSettings>
</configuration>

8.5.2 CanShutdown

指定服务支持 shutdown 服务命令,允许服务控制管理器快速关闭服务。 如果 CanShutdown 为 true,则在系统关机时会通知服务。关机时,如果服务派生类中实现了 OnShutdown 方法,则会调用它。

列表 8.5.2.1 以编程方式设置 CanShutdown

[ChoApplicationHost]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("OnStart");
        base.OnStart(args);
    }

    protected override void ApplyServiceParametersOverrides(ChoServiceInstallerSettings obj)
    {
        obj.CanShutdown = true;
    }

    protected override void OnShutdown()
    {
    }
}

列表 8.5.2.2 通过 ChoServiceInstallerSettings.xml 文件设置 CanShutdown 

打开 ChoServiceInstallerSettings.xml 文件,在 'canShutdown' 属性中指定 true/false。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceInstallerSettings serviceName="TestService" serviceStartMode="Automatic" depends="MSSQL/IIS" account="User" userName="" password="" timeoutInTicks="-1" canHandlePowerEvent="false" canHandleSessionChangeEvent="false" canPauseAndContinue="false" canShutdown="true" canStop="true" autoLog="false" exitCode="0">
    <description>TestService Description</description>
    <parameters><![CDATA[]]></parameters>
    <recoverySettings resetFailedCounterAfter="0">
      <rebootMessage><![CDATA[]]></rebootMessage>
      <command><![CDATA[]]></command>
      <actions><![CDATA[]]></actions>
    </recoverySettings>
  </serviceInstallerSettings>
</configuration>

8.5.3 CanHandlePowerEvent

指定服务 可以处理计算机电源状态更改的通知。 当计算机电源状态更改时,服务控制管理器 (SCM) 使用 CanHandlePowerEvent 的值来验证服务是否接受电源事件命令。

如果 CanHandlePowerEvent 为 true,则命令将被传递给服务,如果定义了 OnPowerEvent 方法,则会调用它。如果派生类中未实现 OnPowerEvent,则 SCM 通过空的基类 ServiceBase.OnPowerEvent 方法处理电源事件。

列表 8.5.3.1 以编程方式设置 CanHandlePowerEvent

[ChoApplicationHost]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("OnStart");
        base.OnStart(args);
    }

    protected override void ApplyServiceParametersOverrides(ChoServiceInstallerSettings obj)
    {
        obj.CanHandlePowerEvent = true;
    }

    protected override bool OnPowerEvent(PowerBroadcastStatus powerStatus)
    {
    }
}

列表 8.5.3.2 通过 ChoServiceInstallerSettings.xml 文件设置CanHandlePowerEvent 

打开 ChoServiceInstallerSettings.xml 文件,在 'canHandlePowerEvent' 属性中指定 true/false。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceInstallerSettings serviceName="TestService" serviceStartMode="Automatic" depends="MSSQL/IIS" account="User" userName="" password="" timeoutInTicks="-1" canHandlePowerEvent="true" canHandleSessionChangeEvent="false" canPauseAndContinue="false" canShutdown="true" canStop="true" autoLog="false" exitCode="0">
    <description>TestService Description</description>
    <parameters><![CDATA[]]></parameters>
    <recoverySettings resetFailedCounterAfter="0">
      <rebootMessage><![CDATA[]]></rebootMessage>
      <command><![CDATA[]]></command>
      <actions><![CDATA[]]></actions>
    </recoverySettings>
  </serviceInstallerSettings>
</configuration>

8.5.4 CanHandleSessionChangedEvent

指定服务 可以处理从终端服务器会话收到的会话更改事件。 

列表 8.5.4.1 以编程方式设置 CanHandleSessionChangedEvent

[ChoApplicationHost]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("OnStart");
        base.OnStart(args);
    }

    protected override void ApplyServiceParametersOverrides(ChoServiceInstallerSettings obj)
    {
        obj.CanHandleSessionChangedEvent = true;
    }

    protected override void OnSessionChange(SessionChangeDescription changeDescription)
    {
    }
}

列表 8.5.4.2 通过 ChoServiceInstallerSettings.xml 文件设置 CanHandleSessionChangedEvent 

打开 ChoServiceInstallerSettings.xml 文件,在 'canHandleSessionChanged' 属性中指定 true/false。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceInstallerSettings serviceName="TestService" serviceStartMode="Automatic" depends="MSSQL/IIS" account="User" userName="" password="" timeoutInTicks="-1" canHandlePowerEvent="false" canHandleSessionChangeEvent="true" canPauseAndContinue="false" canShutdown="true" canStop="true" autoLog="false" exitCode="0">
    <description>TestService Description</description>
    <parameters><![CDATA[]]></parameters>
    <recoverySettings resetFailedCounterAfter="0">
      <rebootMessage><![CDATA[]]></rebootMessage>
      <command><![CDATA[]]></command>
      <actions><![CDATA[]]></actions>
    </recoverySettings>
  </serviceInstallerSettings>
</configuration>

8.5.5 CanStop

指定服务启动后是否可以停止。 当对服务调用 Stop 时,服务控制管理器 (SCM) 使用 CanStop 的值来验证服务是否接受 Stop 命令。对于大多数服务,CanStop 的值为 true,但某些操作系统服务(例如)不允许用户停止它们。

如果 CanStop 为 true,则 Stop 命令将被传递给服务,如果定义了 OnStop 方法,则会调用它。如果派生类中未实现 OnStop,则 SCM 通过空的基类 ServiceBase.OnStop 方法处理 Stop 命令。

列表 8.5.5.1 以编程方式设置 CanStop

[ChoApplicationHost]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("OnStart");
        base.OnStart(args);
    }

    protected override void ApplyServiceParametersOverrides(ChoServiceInstallerSettings obj)
    {
        obj.CanStop = true;
    }

    protected override void OnStop()
    {
    }
}

列表 8.5.5.2 通过 ChoServiceInstallerSettings.xml 文件设置 CanStop 

打开 ChoServiceInstallerSettings.xml 文件,在 'canStop' 属性中指定 true/false。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceInstallerSettings serviceName="TestService" serviceStartMode="Automatic" depends="MSSQL/IIS" account="User" userName="" password="" timeoutInTicks="-1" canHandlePowerEvent="false" canHandleSessionChangeEvent="true" canPauseAndContinue="false" canShutdown="true" canStop="true" autoLog="false" exitCode="0">
    <description>TestService Description</description>
    <parameters><![CDATA[]]></parameters>
    <recoverySettings resetFailedCounterAfter="0">
      <rebootMessage><![CDATA[]]></rebootMessage>
      <command><![CDATA[]]></command>
      <actions><![CDATA[]]></actions>
    </recoverySettings>
  </serviceInstallerSettings>
</configuration>

8.5.6 ExitCode

指定服务的退出代码。在停止服务之前将 ExitCode 属性设置为非零值,以向服务控制管理器指示错误。

列表 8.5.6.1 以编程方式设置 ExitCode

[ChoApplicationHost]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("OnStart");
        base.OnStart(args);
    }

    protected override void ApplyServiceParametersOverrides(ChoServiceInstallerSettings obj)
    {
        obj.ExitCode = -1;
    }
}

列表 8.5.6.2 通过 ChoServiceInstallerSettings.xml 文件设置 ExitCode 

打开 ChoServiceInstallerSettings.xml 文件,在 'exitCode' 属性中指定整数值。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceInstallerSettings serviceName="TestService" serviceStartMode="Automatic" depends="MSSQL/IIS" account="User" userName="" password="" timeoutInTicks="-1" canHandlePowerEvent="false" canHandleSessionChangeEvent="true" canPauseAndContinue="false" canShutdown="true" canStop="true" autoLog="false" exitCode="-1">
    <description>TestService Description</description>
    <parameters><![CDATA[]]></parameters>
    <recoverySettings resetFailedCounterAfter="0">
      <rebootMessage><![CDATA[]]></rebootMessage>
      <command><![CDATA[]]></command>
      <actions><![CDATA[]]></actions>
    </recoverySettings>
  </serviceInstallerSettings>
</configuration>

8.5.7 AutoLog

指定服务是否报告事件日志中的 Start、Stop、Pause 和 Continue 命令。 将 AutoLog 设置为 true 会指示服务使用应用程序事件日志来报告命令失败以及服务上的 Start、Stop、Pause 和 Continue 事件的状态更改信息。服务名称用作日志的 EventLog.Source。

要将信息报告到自定义事件日志而不是应用程序日志,请将 AutoLog 设置为 false,并在 OnContinue、OnPause 或 OnStop 命令处理方法中编写说明,将信息发布到适当的日志。

列表 8.5.7.1 以编程方式设置 AutoLog

[ChoApplicationHost]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("OnStart");
        base.OnStart(args);
    }

    protected override void ApplyServiceParametersOverrides(ChoServiceInstallerSettings obj)
    {
        obj.AutoLog = true;
    }
}

列表 8.5.7.2 通过 ChoServiceInstallerSettings.xml 文件设置 AutoLog 

打开 ChoServiceInstallerSettings.xml 文件,在 'autoLog' 属性中指定 'true/false'。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceInstallerSettings serviceName="TestService" serviceStartMode="Automatic" depends="MSSQL/IIS" account="User" userName="" password="" timeoutInTicks="-1" canHandlePowerEvent="false" canHandleSessionChangeEvent="true" canPauseAndContinue="false" canShutdown="true" canStop="true" autoLog="true" exitCode="-1">
    <description>TestService Description</description>
    <parameters><![CDATA[]]></parameters>
    <recoverySettings resetFailedCounterAfter="0">
      <rebootMessage><![CDATA[]]></rebootMessage>
      <command><![CDATA[]]></command>
      <actions><![CDATA[]]></actions>
    </recoverySettings>
  </serviceInstallerSettings>
</configuration>

8.5.7 Parameters

指定服务 命令行参数。在安装服务期间传递的命令行参数将永久保存在注册表中,并在每次服务启动时自动使用。

在启动服务期间传递的命令行参数将在服务运行会话期间临时使用。 

列表 8.5.7.1 以编程方式设置 Parameters

[ChoApplicationHost]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("OnStart");
        base.OnStart(args);
    }

    protected override void ApplyServiceParametersOverrides(ChoServiceInstallerSettings obj)
    {
        obj.SetServiceArguments(@"/name:Mark /msg:Hello");
    }
}

列表 8.5.7.2 通过 ChoServiceInstallerSettings.xml 文件设置 Parameters 

打开 ChoServiceInstallerSettings.xml 文件,在 'parameters' 属性中指定服务参数。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceInstallerSettings serviceName="TestService" serviceStartMode="Automatic" depends="MSSQL/IIS" account="User" userName="" password="" timeoutInTicks="-1" canHandlePowerEvent="false" canHandleSessionChangeEvent="true" canPauseAndContinue="false" canShutdown="true" canStop="true" autoLog="true" exitCode="-1">
    <description>TestService Description</description>
    <parameters><![CDATA[/name:Mark /msg:Hello]]></parameters>
    <recoverySettings resetFailedCounterAfter="0">
      <rebootMessage><![CDATA[]]></rebootMessage>
      <command><![CDATA[]]></command>
      <actions><![CDATA[]]></actions>
    </recoverySettings>
  </serviceInstallerSettings>
</configuration>

8.6 服务恢复

Windows 服务支持在发生故障时自动执行某些已定义操作的能力。Cinchoo 框架允许您定义可以在第一次、第二次及后续故障时执行的操作,还支持重置故障计数器以及在采取操作之前等待多长时间。允许的操作包括:

  • 不采取任何操作(默认)
  • 重新启动服务
  • 运行程序
  • 重新启动计算机

从开发者的角度来看,拥有这种功能非常有帮助。如果您免费获得它,谁还需要重新发明轮子并为服务编写恢复代码。此外,它允许将恢复作为 IT 任务进行重新配置,而不是重建软件。

8.6.1 ResetFailedCounterAfter

指定没有故障后的时间段(以秒为单位),之后故障计数将重置为 0(零)。 如果要重置计数器,可以将其设置为零,这将导致计数器在每次故障后重置。

列表 8.6.1.1 以编程方式设置 ResetFailedCounterAfter

[ChoApplicationHost]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("OnStart");
        base.OnStart(args);
    }

    protected override void ApplyServiceParametersOverrides(ChoServiceInstallerSettings obj)
    {
        obj.RecoverySettings.ResetFailCountAfter(100);
    }
}

列表 8.6.1.2 通过 ChoServiceInstallerSettings.xml 文件设置 ResetFailedCounterAfter 

打开 ChoServiceInstallerSettings.xml 文件,在 'resetFailedCounterAfter' 属性中指定秒值。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceInstallerSettings serviceName="TestService" serviceStartMode="Automatic" depends="MSSQL/IIS" account="User" userName="" password="" timeoutInTicks="-1" canHandlePowerEvent="false" canHandleSessionChangeEvent="true" canPauseAndContinue="false" canShutdown="true" canStop="true" autoLog="true" exitCode="-1">
    <description>TestService Description</description>
    <parameters><![CDATA[/name:Mark /msg:Hello]]></parameters>
    <recoverySettings resetFailedCounterAfter="1000">
      <rebootMessage><![CDATA[]]></rebootMessage>
      <command><![CDATA[]]></command>
      <actions><![CDATA[]]></actions>
    </recoverySettings>
  </serviceInstallerSettings>
</configuration>

8.6.2 RestartService

将服务指定为重新启动的故障操作。 服务将在指定的时间段(以分钟为单位)之后自动重新启动。

列表 8.6.2.1 以编程方式设置 RestartService

[ChoApplicationHost]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("OnStart");
        base.OnStart(args);
    }

    protected override void ApplyServiceParametersOverrides(ChoServiceInstallerSettings obj)
    {
        obj.RecoverySettings.RestartService(10);
    }
}

列表 8.6.2.2 通过 ChoServiceInstallerSettings.xml 文件设置 RestartService 

打开 ChoServiceInstallerSettings.xml 文件,在 'actions' 元素中指定 'restart/600000'。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceInstallerSettings serviceName="TestService" serviceStartMode="Automatic" depends="MSSQL/IIS" account="User" userName="" password="" timeoutInTicks="-1" canHandlePowerEvent="false" canHandleSessionChangeEvent="true" canPauseAndContinue="false" canShutdown="true" canStop="true" autoLog="true" exitCode="-1">
    <description>TestService Description</description>
    <parameters><![CDATA[/name:Mark /msg:Hello]]></parameters>
    <recoverySettings resetFailedCounterAfter="1000">
      <rebootMessage><![CDATA[]]></rebootMessage>
      <command><![CDATA[]]></command>
      <actions><![CDATA[restart/600000]]></actions>
    </recoverySettings>
  </serviceInstallerSettings>
</configuration>

8.6.4 RebootSystem

将服务指定为重新启动系统的故障操作。SCM 将在指定的时间段(以分钟为单位)之后自动重新启动系统。

列表 8.6.4.1 以编程方式设置 RunProgram

[ChoApplicationHost]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("OnStart");
        base.OnStart(args);
    }

    protected override void ApplyServiceParametersOverrides(ChoServiceInstallerSettings obj)
    {
        obj.RecoverySettings.RebootSystem(10, "Service down.");
    }
}

列表 8.6.4.2 通过 ChoServiceInstallerSettings.xml 文件设置 RunProgram 

打开 ChoServiceInstallerSettings.xml 文件,在 'actions' 元素中指定 'reboot/600000',并在 'rebootMessage' 元素中指定 'Service down.'。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceInstallerSettings serviceName="TestService" serviceStartMode="Automatic" depends="MSSQL/IIS" account="User" userName="" password="" timeoutInTicks="-1" canHandlePowerEvent="false" canHandleSessionChangeEvent="true" canPauseAndContinue="false" canShutdown="true" canStop="true" autoLog="true" exitCode="-1">
    <description>TestService Description</description>
    <parameters><![CDATA[/name:Mark /msg:Hello]]></parameters>
    <recoverySettings resetFailedCounterAfter="1000">
      <rebootMessage><![CDATA[]]></rebootMessage>
      <command><![CDATA[]]></command>
      <actions><![CDATA[run/600000]]></actions>
    </recoverySettings>
  </serviceInstallerSettings>
</configuration>

8.6.3 RunProgram

将服务指定为运行指定程序的故障操作。SCM 将在指定的时间段(以分钟为单位)之后自动启动指定程序。

列表 8.6.3.1 以编程方式设置 RunProgram

[ChoApplicationHost]
public class AppHost : ChoApplicationHost
{
    protected override void OnStart(string[] args)
    {
        Console.WriteLine("OnStart");
        base.OnStart(args);
    }

    protected override void ApplyServiceParametersOverrides(ChoServiceInstallerSettings obj)
    {
        obj.RecoverySettings.RunProgram(10, "Notepad.exe", @"C:\sample.txt");
    }
}

列表 8.6.3.2 通过 ChoServiceInstallerSettings.xml 文件设置 RunProgram 

打开 ChoServiceInstallerSettings.xml 文件,在 'actions' 元素中指定 'run/600000',并在 'command' 元素中指定 'Notepad.exe C:\sample.txt'。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <serviceInstallerSettings serviceName="TestService" serviceStartMode="Automatic" depends="MSSQL/IIS" account="User" userName="" password="" timeoutInTicks="-1" canHandlePowerEvent="false" canHandleSessionChangeEvent="true" canPauseAndContinue="false" canShutdown="true" canStop="true" autoLog="true" exitCode="-1">
    <description>TestService Description</description>
    <parameters><![CDATA[/name:Mark /msg:Hello]]></parameters>
    <recoverySettings resetFailedCounterAfter="1000">
      <rebootMessage><![CDATA[]]></rebootMessage>
      <command><![CDATA[Notepad.exe C:\sample.txt]]></command>
      <actions><![CDATA[run/600000]]></actions>
    </recoverySettings>
  </serviceInstallerSettings>
</configuration>

请收藏本文,更多更新即将推出。

© . All rights reserved.