Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#3.5

Cinchoo - Simplified Windows Services Development

2.78/5 (6 votes)
27 Oct 2014CPOL29 min read 18.9K   109  
Easy to create and use windows services, self install-able, multiple instances etc

Contents

1. Introduction

Cinchoo is the application framework for .NET. One of the main functionalities it provides to the users is application configuration management. Application configuration is the information that application reads and/or writes at run-time from the source.

One another important feature it offers to the developers community is the unified, generic application host to build and run application in different modes. Code once, run the application as either Console, Windows, WPF, Windows Service or Windows Tray application.

In this article, I'm going to illustrate how to use this library to create Windows Service application. It is a simpler, fluent model for configuring everything about your service in one place. The more compelling reason is that you can still execute the application as a simple console application, allowing you to do step-through debugging without jumping through the hoops required by a service. Making it as library letting you to concentrate yourself on the core development tasks. Cinchoo provides a clean and easy API to develop and run Windows Service applications. It allows you

  1. Self installable service application
  2. Install and run multi-instances of services
  3. Able to run as Console application for ease of debugging
  4. Pass service arguments via command line
  5. Arguments are saved and used when service is automatically started

2. Requirement

The application host library is written in C# for the .NET 4.0 Framework. It is part of Cinchoo framework, which is a great library with lot of features like Configuration Management, common ApplicationHost, Shell features etc.

3. "Hello World!" Sample

Lets begin by looking into a simple example of a windows service application printing 'Hello World!' message into log file. 

Download the latest Cinchoo binary here. (Nuget Command: Install-Package Cinchoo)

  • Open VS.NET 2010 or higher
  • Create a sample VS.NET (.NET Framework 4) Console Application project
  • Add reference to Cinchoo.Core.dll
  • Use the Cinchoo.Core namespace
  • Copy and paste the below application host object

Listing 3.1 Defining ApplicationHost object

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

The code above illustrates about defining ApplicationHost object. First thing define a ApplicationHost (ex. HelloWorldAppHost) class from ChoApplicationHost, it indicates that this object is a ApplicationHost object. And it must be decorated with ChoApplicationHostAttribute to complete the definition. In this example, we override OnStart method with printing "Hello World!" message to log file.

Listing 3.2 Main Method

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

We start by calling ChoApplication.Run() method in the main entry of the application. That all. All the heavy lifting of installing, running the application as service is done by the library under the hood. Now your application is service enabled application. It can also be run as Console Application for easy debugging the service application.

Listed below are the steps to install, uninstall, start and stop the service 

Listing 3.3 Install HelloWorld.exe service

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

[SC] CreateService SUCCESS

[SC] ChangeServiceConfig SUCCESS

Listing 3.4 Start HelloWorld.exe service

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

Listing 3.5 Stop HelloWorld.exe service

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

Listing 3.6 Uninstall HelloWorld.exe service

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

[SC] DeleteService SUCCESS

Listing 3.7 HelloWorld.exe with /@? argument

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.

'@?' argument will print out the service level arguments accepted by HelloWorld application. 

Listing 3.8 Install HelloWorld.exe service with 'Test1' name

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

[SC] DeleteService SUCCESS

Listing 3.9 Run HelloWorld.exe as console application

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

        Hello world!

4. Defining Application Host Object

4.1 ChoApplicationHostAttribute

All application host objects must be decorated by ChoApplicationHostAttribute. An application must have atleast one application host object defined. Cinchoo framework will discover them at the application startup. 

4.2 ChoApplicationHost

All application host objects must be derived from ChoApplicationHost class. Override nessasary overrides in them. An application must have one application host object defined either in the entry assembly or referenced assemblies. In this object, you can override number of methods for your needs.

4.2.1 OnStart() Method

When implemented in a derived class, executes when a Start command is sent to the service by the Service Control Manager (SCM) or when the operating system starts (for a service that starts automatically) or when the application passed with '/@S' switch or when application starts as console application.

Use OnStart to specify the processing that occurs when the service receives a Start command. OnStart is the method in which you specify the behavior of the service. OnStart can take arguments as a way to pass data.

Do not use the constructor to perform processing that should be in OnStart. Use OnStart to handle all initialization of your service. The constructor is called when the application's executable runs, not when the service runs. The executable runs before OnStart. When you continue, for example, the constructor is not called again because the SCM already holds the object in memory. If OnStop releases resources allocated in the constructor rather than in OnStart, the needed resources would not be created again the second time the service is called.

Process initialization arguments for the service in the OnStart method, not in the Main method. The arguments in the args parameter array can be set manually in the properties window for the service in the Services console or can be passed via command line argument with '/@SP' switch. 

4.2.2 OnStop() Method

When implemented in a derived class, executes when a Stop command is sent to the service by the Service Control Manager (SCM) or when the application passed with '/@T' switch. Specifies actions to take when a service stops running. When implemented in a derived class, executes when a Stop command is sent to the service by the Service Control Manager (SCM). Specifies actions to take when a service stops running.

When the SCM receives a Stop command, it uses the value of ChoServiceInstallerSettings.CanStop to verify whether the service accepts Stop commands. If ChoServiceInstallerSettings.CanStop is true, the Stop command is passed to the service, and the OnStop method is called if it is defined. If OnStop is not implemented in the service, the SCM handles the Stop command. If ChoServiceInstallerSettings.CanStop is false, the SCM ignores the Stop command. 

4.2.3 OnContinue() Method

When implemented in a derived class, OnContinue runs when a Continue command is sent to the service by the Service Control Manager (SCM) or when the application passed with '/@C' switch. Specifies actions to take when a service resumes normal functioning after being paused.

Implement OnContinue to mirror your application's response to OnPause. When you continue the service (either through the Services console or programmatically), the OnContinue processing runs, and the service becomes active again.

OnContinue is expected to be overridden when the ChoServiceInstallerSettings.CanPauseAndContinue property is true. If ChoServiceInstallerSettings.CanPauseAndContinue is false, the SCM will not pass Pause or Continue requests to the service, so the OnPause and OnContinue methods will not be called even if they are implemented. In the SCM, the Pause and Continue controls are disabled when ChoServiceInstallerSettings.CanPauseAndContinue is false.

4.2.4 OnPause() Method

When implemented in a derived class, executes when a Pause command is sent to the service by the Service Control Manager (SCM) or when the application passed with '/@P' switch. Specifies actions to take when a service pauses.

Use OnPause to specify the processing that occurs when the service receives a Pause command. OnPause is expected to be overridden when the ChoServiceInstallerSettings.CanPauseAndContinue property is true. When you continue a paused service (either through the Services console or programmatically via '/@P' switch), the OnContinue processing is run, and the service becomes active again.

Sending a Pause request to the service can conserve system resources because Pause need not release all system resources. For example, if threads have been opened by the process, pausing a service rather than stopping it can allow the threads to remain open, obviating the need to reallocate them when the service continues. If you define Pause to release all system resources, it behaves like a Stop command.

Set ChoServiceInstallerSettings.CanPauseAndContinue to true, and override OnPause and OnContinue to specify the processing that should occur when the SCM passes a Pause or Continue request to your service. OnContinue should be implemented to undo the processing in OnPause.

If ChoServiceInstallerSettings.CanPauseAndContinue is false, the SCM will not pass Pause or Continue requests to the service, so the OnPause and OnContinue methods will not be called even if implemented. In the SCM, the Pause and Continue controls are disabled when ChoServiceInstallerSettings.CanPauseAndContinue is false.

4.2.5 OnPowerEvent() Method

When implemented in a derived class, executes when the computer's power status has changed. This applies to laptop computers when they go into suspended mode, which is not the same as a system shutdown.

Use OnPowerEvent to specify the processing that occurs when the system event indicated in the System.ServiceProcess.PowerBroadcastStatus enumeration occurs--for example, when the computer is placed in suspended mode or indicates low battery power.

OnPowerEvent is expected to be overridden when the ChoServiceInstallerSettings.CanHandlePowerEvent property is true.

4.2.6 OnShutdown() Method

When implemented in a derived class, executes when the system is shutting down. Specifies what should occur immediately prior to the system shutting down.

Use OnShutdown to specify the processing that occurs when the system shuts down. This event occurs only when the operating system is shut down, not when the computer is turned off. OnShutdown is expected to be overridden when the ChoServiceInstallerSettings.CanShutdown property is true.

4.2.7 OnCustomCommand() Method

When implemented in a derived class, OnCustomCommand executes when the Service Control Manager (SCM) passes a custom command to the service or when the application passed with '/@E' switch . Specifies actions to take when a command with the specified parameter value occurs.

OnCustomCommand lets you specify additional functionality beyond starting, stopping, pausing and continuing services. The SCM does not examine the custom command to verify whether the service supports the command parameter passed in. It passes the custom command directly to the service. If the service does not recognize the command parameter, it does nothing. 

Custom commands are raised by an ExecuteCommand statement in a ServiceController component or by passing command through '/@E' command line switch. Use a switch statement or if..then condition to handle the custom commands you define on your service. The only values for a custom command that you can define in your application or use in OnCustomCommand are those between 128 and 255. Integers below 128 correspond to system-reserved values.

If the ChoServiceInstallerSettings.AutoLog property is true, custom commands, like all other commands, write entries to the event log to report whether the method execution succeeded or failed.

4.2.8 OnSessionChange() Method

Executes when a change event is received from a Terminal Server session. You must set the ChoServiceInstallerSettings.CanHandleSessionChangeEvent property to true to enable the execution of this method.

4.2.9 RequestAdditionalTime() Method

Requests additional time for a pending operation. The RequestAdditionalTime method is intended to be called by the overridden OnContinue, OnPause, OnStart, or OnStop methods to request additional time for a pending operation, to prevent the Service Control Manager (SCM) from marking the service as not responding. If the pending operation is not a continue, pause, start, or stop, an InvalidOperationException is thrown.

4.2.10 ApplyGlobalApplicationSettingsOverrides() Method

When implemented in a derived class, ApplyGlobalApplicationSettingsOverrides executes when the framework initializes. In here you can overrides ChoGlobalApplicationSettings members.

4.2.11 ApplyAppFrxSettingsOverrides() Method

When implemented in a derived class, ApplyAppFrxSettingsOverrides executes when the framework initializes. In here you can overrides ChoAppFrxSettings members.

4.2.12 ApplyMetaDataFilePathSettingsOverrides() Method

When implemented in a derived class, ApplyMetaDataFilePathSettingsOverrides executes when the framework initializes. In here you can overrides ChoMetaDataFilePathSettings members.

4.2.13 BeforeInstall() Method

When implemented in a derived class, BeforeInstall() method executes before the service install happens Note that this action is only executed if the service is being installed.

4.2.14 AfterInstall() Method

When implemented in a derived class, AfterInstall() method executes after the service install happens Note that this action is only executed if the service is being installed.

4.2.15 BeforeUninstall() Method

When implemented in a derived class, BeforeUninstall() method executes before the service uninstall happens Note that this action is only executed if the service is being uninstalled.

4.2.16 AfterUninstall() Method

When implemented in a derived class, AfterUninstall() method executes after the service uninstall happens Note that this action is only executed if the service is being uninstalled.

5. Managing Services

Using Cinchoo framework for developing windows service application provides many options via command line arguments to self-install, execute and control the service application.

5.1 Install Service

If you’re developing a Windows Service by using the .NET Framework, you usually install your service applications by using a command-line utility called InstallUtil.exe. You do not need this utility anymore when using Cinchoo framework for your service development. These services are self-installable.

5.1.1 Install Single Instance Service

By default, a service application developed using Cinchoo framework are single instance service application. It means that you can install and run atmost one instance of it at any time. By passing '/@I' command line argument to service executable will install the service with the executable name as service name. For the sample below, the 'HelloWorld' service will be installed in your machine.

Listing 5.1.1.1 Install service

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

[SC] CreateService SUCCESS

[SC] ChangeServiceConfig SUCCESS

5.1.2 Install Multi Instance Service

Sometime you may want to install multiple services with different names. You can do so by turning off 'SingleInstanceApp' flag in the ChoGlobalApplicationSettings class. Please visit the below url on how to turn off this option in the application.

Cinchoo – Allow multi-instance application

The below sample shows how to install a service with a 'TestService' name by using '/@SN' command line switch.

Listing 5.1.2.1 Install 'TestService' service

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

[SC] CreateService SUCCESS

[SC] ChangeServiceConfig SUCCESS

5.1.2 Uninstall Service

To uninstall a service, you must use '/@U' command line switch. The below samples shows how to uninstall a service

Listing 5.1.2.1 Uninstall service

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

[SC] DeleteService SUCCESS

Listing 5.1.2.2 Uninstall 'TestService' service

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

[SC] DeleteService SUCCESS

5.1.3 Start Service

To start a service, you must use '/@S' command line switch. The below samples shows how to start a service

Listing 5.1.3.1 Start service

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

[SC] DeleteService SUCCESS

Listing 5.1.3.2 Start 'TestService' service

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

5.1.3 Stop Service

To stop a service, you must use '/@T' command line switch. SCM uses the value of ChoServiceInstallerSettings.CanStop to verify whether the service accepts Stop commands. If ChoServiceInstallerSettings.CanStop is true, the Stop command is passed to the service, and the OnStop method is called if it is defined. If OnStop is not implemented in the service, the SCM handles the Stop command. If ChoServiceInstallerSettings.CanStop is false, the SCM ignores the Stop command. 

The below samples shows how to stop a service

Listing 5.1.3.1 Stop service

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

[SC] DeleteService SUCCESS

Listing 5.1.3.2 Stop 'TestService' service

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

5.1.4 Continue Service

To continue a service, you must use '/@C' command line switch.

SCM uses the value of ChoServiceInstallerSettings.CanPauseAndContinue to verify whether the service accepts Continue commands. If ChoServiceInstallerSettings.CanPauseAndContinue is true, the Continue command is passed to the service, and the OnContinue method is called if it is defined. If OnContinue is not implemented in the service, the SCM handles the Continue command. If ChoServiceInstallerSettings.CanPauseAndContinue is false, the SCM ignores the Continue command. 

The below samples shows how to continue a service

Listing 5.1.4.1 Continue service

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

[SC] DeleteService SUCCESS

Listing 5.1.4.2 Continue 'TestService' service

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

5.1.5 Pause Service

To pause a service, you must use '/@P' command line switch.

SCM uses the value of ChoServiceInstallerSettings.CanPauseAndContinue to verify whether the service accepts Pause commands. If ChoServiceInstallerSettings.CanPauseAndContinue is true, the Pause command is passed to the service, and the OnPause method is called if it is defined. If OnPause is not implemented in the service, the SCM handles the Pause command. If ChoServiceInstallerSettings.CanPauseAndContinue is false, the SCM ignores the Pause command. 

The below samples shows how to pause a service

Listing 5.1.5.1 Continue service

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

[SC] DeleteService SUCCESS

Listing 5.1.5.2 Continue 'TestService' service

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

5.1.5 Execute Custom Command

To execute a custom command, you must use '/@E' command line switch with command identifier (integer).

The only values for a custom command that you can define in your application or use in OnCustomCommand are those between 128 and 255. Integers below 128 correspond to system-reserved values.

The below samples shows how to pause a service

Listing 5.1.5.1 Execute Custom Command

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

[SC] DeleteService SUCCESS

Listing 5.1.5.2 Execute Custom Command on 'TestService' service

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

5.1.6 Service Arguments

Of course every application needs some arguments to run against occasionally to initialize the process. Windows services are indeed no exceptions. There are two different types of arguments you can define for the services

  • Permanent
  • One-Time

The arguments can be passed to the services using '/@SP' command line switch. There arguments are passed to OnStart() method by the infrastructure automatically.

Arguments passed while installing services will be saved permanently in the registry. All the subsequent runs, these parameters are retrived by SCM and passed to service OnStart() automatically.

Listing 5.1.6.1 Permanent Service Arguments

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

[SC] CreateService SUCCESS

[SC] ChangeServiceConfig SUCCESS

Sometime you may want to override the arguments when starting the services. You can do so by passing the arguments in number of ways

  • By passing arguments via command line when starting service
  • The arguments in the args parameter array can be set manually in the properties window for the service in the Services console.

In the sample below, the arguments passed while starting the service will be a one-time basis arguments.

Listing 5.1.5.2 One-Time service arguments

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

6. Application Host Discovery

To successfully deploy your Windows Service application, you must understand how the Cinchoo framework locates and loads the Application Host object that make up your application. By default, Cinchoo framework attempts to locates and loads Application Host object from entry assembly. This default behavior can be overridden by configuration file settings.

Cinchoo framework performs a number of steps when attempting to locate Application Host object.

  1. Examining the App.Cofig/Web.Config file
  2. Locate the ApplicationHost object in Entry assembly
  3. Locate first discovered ApplicationHost object in the referenced assemblies.

6.1 Examine in App.Config/Web.Config file

Cinchoo framework checks the application configuration file for information that overrides the application host object information. The following code provides a example of specifying application host information in the application configuration file

Listing 6.1.1 App.Config file

XML
<?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 Locate in Entry Assembly

Cinchoo framework checks for the application host object defined in the entry assembly when there is no type specified in the configuration file.

6.3 Locate first discovered ApplicationHost object

Cinchoo framework scans all the referenced assemblies for the application host object defined in them and use the first discovered such object to manage the Windows Service. This step happens when the framework failed to locate the application host object from previous steps.

7. Customization

There are ways to customize your windows service application, like service start mode, service identify, custom install actions, service dependencies etc. The default settings should be good enough for most applications, but they are there for your customizations if you need to.

Customization can be done in couple of ways

  • Programmatically
  • Configuration file

7.1 Configuration File

All the customizable parameters are defined in the ChoServiceInstallerSettings.xml file under Config folder.

Below is the sample contents of the configuration file

Listing 7.1.1 ChoServiceInstallerSettings.xml file

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 Programmatically

This is one another way to customize your windows service application programmatically.

Here is the sample on how to do

Listing 7.1.1 Override Service Installer Settings

C#
[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. Configuration

Once Cinchoo framework is added to your project for your services development, you can configure the services using framework API or through configuration file. In this section, will talk about most common configuration parameters used by services and how you can manipulate them via API/Configration file.

8.1 Service Configuration

8.1.1 Service Name

Specify the base name of the service, as it is registered in the services control manager. This setting is optional and by default uses entry assembly (executable) name.

It is recommended that service names does not contains spaces or other whitespace characters.

Listing 8.1.1.1 Set ServiceName programmatically

C#
[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";
    }
}

Listing 8.1.1.2 Set ServiceName via ChoServiceInstallerSettings.xml file

Open ChoServiceInstallerSettings.xml file, specify the service name in 'serviceName' attribute.

XML
<?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>

Listing 8.1.1.3 Set ServiceName via command line option

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

The order of taking the service names are as follows,

  1. Command line option (/@SN)
  2. Programmatically
  3. ChoServiceInstallerSettings.xml file

Each service on the system must have a unique name. If you need to run multiple instances of the same service, consider using the InstanceName command-line option when installing the service.

8.1.2 Display Name

Specify the display name of the service in the services control manager. This setting is optional and defaults to the service name.

Listing 8.1.2.1 Set DisplayName programmatically

C#
[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";
    }
}

Listing 8.1.2.2 Set DisplayName via command line option

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

The order of taking the display names are as follows,

  1. Command line option (/@DN)
  2. Programmatically

8.1.3 Instance Name

Specify the instance name of the service. It is combined with the service name and seperated by $. This setting is optional and only added if specified.

Listing 8.1.3.1 Set InstanceName programmatically

C#
[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";
    }
}

Listing 8.1.3.2 Set InstanceName via command line option

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

The order of taking the display names are as follows,

  1. Command line option (/@IN)
  2. Programmatically

This option is typically set to run multiple instances of the same service.

8.1.4 Service Description

Specify the description of the service in the services control manager. This is optional and defaults to the service name.

Listing 8.1.4.1 Set ServiceDescription programmatically

C#
[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";
    }
}

Listing 8.1.4.2 Set ServiceDescription via ChoServiceInstallerSettings.xml file

Open ChoServiceInstallerSettings.xml file, specify the service description in 'description' element.

XML
<?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>

Listing 8.1.4.3 Set ServiceDescription via command line option

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

The order of taking the service description are as follows,

  1. Command line option (/@SD)
  2. Programmatically
  3. ChoServiceInstallerSettings.xml file

8.2 Service Start Modes

There are multiple service start modes, each of which can be specified by the configuration. This option is only used if the service is being installed.

  1. DelayedAutomatic
  2. Automatic
  3. Manual
  4. Disabled

Listing 8.2.1 Set ServiceStartMode via ChoServiceInstallerSettings.xml file

Open ChoServiceInstallerSettings.xml file, specify the mode in 'serviceStartMode' attribute.

XML
<?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 Service Identity

Services can be configured to run as a number of different identities, using the configuration option that is most appropriate.

Possible identies are

  1. Network Service
  2. Local System (Default)
  3. Local Service
  4. User

8.3.1 Network Service Account

Runs the service using the NETWORK_SERVICE built-in account. The network service account is a predefined local account used by the SCM. A service that runs in the context of the NetworkService account presents the computer's credentials to remote servers. You can set the service to run on this account as below

Listing 8.3.1.1 Set Identity as Network Service account programmatically

C#
[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();
    }
}

Listing 8.3.1.2 Set Identity as Network Service account via ChoServiceInstallerSettings.xml file

Open ChoServiceInstallerSettings.xml file, specify the account as 'NetworkService' in 'account' attribute.

XML
<?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 Local System Account

Runs the service using the local system account. The LocalSystem account is a predefined local account used by the service control manager.  It has extensive privileges on the local computer, and acts as the computer on the network. A service that runs in the context of the LocalSystem account inherits the security context of the SCM. The account is not associated with any logged-on user account. It is the default account set to when you install a service. You can set the service to run on this account explicitly as below

Listing 8.3.2.1 Set Identity as Local System account programmatically

C#
[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();
    }
}

Listing 8.3.2.2 Set Identity as Local System via ChoServiceInstallerSettings.xml file

Open ChoServiceInstallerSettings.xml file, specify the account as 'LocalSystem' in 'account' attribute.

XML
<?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 Local Service Account

Runs the service using the local service account. The LocalService account is a predefined local account used by the service control manager.  It has minimum privileges on the local computer and presents anonymous credentials on the network.

Listing 8.3.3.1 Set Identity as Local System account programmatically

C#
[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();
    }
}

Listing 8.3.3.2 Set Identity as Local System via ChoServiceInstallerSettings.xml file

Open ChoServiceInstallerSettings.xml file, specify the account as 'LocalService' in 'account' attribute.

XML
<?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 User Account

Runs the service using the specified username and password. User name may be specified either as "<domain>\<username>" or  "<username>". It can be configured as follows

Listing 8.3.4.1 Set Identity as User account programmatically

C#
[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");
    }
}

Listing 8.3.4.2 Set Identity as User Account via ChoServiceInstallerSettings.xml file

Open ChoServiceInstallerSettings.xml file, specify the account as 'User' in 'account' attribute. Then specify the username and password in the corresponding 'userName' and 'password' attributes. Keeping password as plain text in the configuration file is not a safe.

XML
<?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 Prompt User Account

When the service is installed, the installer will prompt for the username/password combination used to launch the service. User name may be specified either as "<domain>\<username>" or  "<username>". It can be configured as follows

Listing 8.3.5.1 Set Identity as User account to be prompted programmatically

C#
[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();
    }
}

Listing 8.3.5.2 Set Identity as User account to be prompted via ChoServiceInstallerSettings.xml file

Open ChoServiceInstallerSettings.xml file, specify the account as 'User' in 'account' attribute. Then empty the username and password in the corresponding 'userName' and 'password' attributes.

XML
<?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 Service Dependencies

Specifies the names of services that must start before this service starts. The names are separated by forward slashes (/).  This is managed by the windows services control manager.

Listing 8.4.1 Set Service Depend programmatically

C#
[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");
    }
}

Listing 8.4.2 Set Service Depend via ChoServiceInstallerSettings.xml file

Open ChoServiceInstallerSettings.xml file, specify the dependent service names in 'depends' attribute. The names must be seperated by slashes(/).

XML
<?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 Advanced Settings

8.5.1 CanPauseAndContinue

Specifies that the service supports pause and continue, allowing the services control manager to pass pause and continue commands to the service.

When a service is paused, it halts what it is doing. When you continue the service (either through the Service Control Manager or programmatically), OnContinue runs. Sending a Pause request to the service can conserve system resources. Pause may not release all system resources, but Stop does. OnPause and OnContinue are often implemented to perform less processing than OnStop and OnStart.

When CanPauseAndContinue is true, override OnPause and OnContinue to specify the processing that should occur when the Service Control Manager (SCM) passes a Pause or Continue request to your service. OnContinue should be implemented to undo the processing in OnPause.

If CanPauseAndContinue is false, the SCM will not pass Pause or Continue requests to the service, so the OnPause and OnContinue methods will not be called even if they are implemented. In the SCM, the Pause and Continue controls are disabled when CanPauseAndContinue is false.

Listing 8.5.1.1 Set CanPauseAndContinue programmatically

C#
[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()
    {
    }
}

Listing 8.5.1.2 Set CanPauseAndContinue via ChoServiceInstallerSettings.xml file

Open ChoServiceInstallerSettings.xml file, specify the true/false in 'canPauseAndContinue' attribute.

XML
<?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

Specifies that the service supports the shutdown service command, allowing the services control manager to quickly shutdown the service. If CanShutdown is true, the service is notified when the system is shutting down. At shutdown, the OnShutdown method is called if it has been implemented in your derived class.

Listing 8.5.2.1 Set CanShutdown programmatically

C#
[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()
    {
    }
}

Listing 8.5.2.2 Set CanShutdown via ChoServiceInstallerSettings.xml file

Open ChoServiceInstallerSettings.xml file, specify the true/false in 'canShutdown' attribute.

XML
<?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

Specifies that the service can handle notifications of computer power status changes. When the computer power status changes, the Service Control Manager (SCM) verifies whether the service accepts power event commands using the value of CanHandlePowerEvent.

If CanHandlePowerEvent is true, the command is passed to the service and the OnPowerEvent method is called if defined. If OnPowerEvent is not implemented in the derived class, the SCM handles the power event through the empty base class ServiceBase.OnPowerEvent method.

Listing 8.5.3.1 Set CanHandlePowerEvent programmatically

C#
[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)
    {
    }
}

Listing 8.5.3.2 Set CanHandlePowerEvent via ChoServiceInstallerSettings.xml file

Open ChoServiceInstallerSettings.xml file, specify the true/false in 'canHandlePowerEvent' attribute.

XML
<?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

Specifies that the service can handle session change events received from a Terminal Server session. 

Listing 8.5.4.1 Set CanHandleSessionChangedEvent programmatically

C#
[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)
    {
    }
}

Listing 8.5.4.2 Set CanHandleSessionChangedEvent via ChoServiceInstallerSettings.xml file

Open ChoServiceInstallerSettings.xml file, specify the true/false in 'canHandleSessionChanged' attribute.

XML
<?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

Specifies whether the service can be stopped once it has started. When Stop is called on a service, the Service Control Manager (SCM) verifies whether the service accepts Stop commands using the value of CanStop. For most services, the value of CanStop is true, but some operating system services, for example, do not allow the user to stop them.

If CanStop is true, the Stop command is passed to the service and the OnStop method is called if it is defined. If OnStop is not implemented in the derived class, the SCM handles the Stop command through the empty base class ServiceBase.OnStop method.

Listing 8.5.5.1 Set CanStop programmatically

C#
[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()
    {
    }
}

Listing 8.5.5.2 Set CanStop via ChoServiceInstallerSettings.xml file

Open ChoServiceInstallerSettings.xml file, specify the true/false in 'canStop' attribute.

XML
<?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

Specifies exit code of the service. Set the ExitCode property to a non-zero value before stopping the service to indicate an error to the Service Control Manager.

Listing 8.5.6.1 Set ExitCode programmatically

C#
[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;
    }
}

Listing 8.5.6.2 Set ExitCode via ChoServiceInstallerSettings.xml file

Open ChoServiceInstallerSettings.xml file, specify the integer value in 'exitCode' attribute.

XML
<?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

Specifies the service whether to report Start, Stop, Pause, and Continue commands in the event log. Setting AutoLog to true instructs the service to use the Application event log to report command failures, as well as state change information for Start, Stop, Pause, and Continue events on the service. The name of the service is used as the log's EventLog.Source.

To report information to a custom event log rather than the Application log, set AutoLog to false and write instructions within the command-handling methods OnContinue, OnPause, or OnStop to post to the appropriate log.

Listing 8.5.7.1 Set AutoLog programmatically

C#
[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;
    }
}

Listing 8.5.7.2 Set AutoLog via ChoServiceInstallerSettings.xml file

Open ChoServiceInstallerSettings.xml file, specify 'true/false' in 'autoLog' attribute.

XML
<?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

Specifies the service command line arguments. The command line arguments set during installation service will be saved permanently in the registry and used automatically everyone the service is started.

The command line arguments passed during start of the service will be used temporary during the running session of the service. 

Listing 8.5.7.1 Set Parameters programmatically

C#
[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");
    }
}

Listing 8.5.7.2 Set Parameters via ChoServiceInstallerSettings.xml file

Open ChoServiceInstallerSettings.xml file, specify service arguments' in 'parameters' attribute.

XML
<?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 Service Recovery

Windows Services support the ability to automatically perform some defined action in response to a failure. Cinchoo framework allows you to define actions that can be performed on the 1st failure, 2nd failure, and subsequent failures, and also provides support for resetting the failure counters and how long to wait before taking the action. The allowed actions are

  • Take No Action (default)
  • Restart the Service
  • Run a Program
  • Restart the Computer

Having this type of functionality is really helpful from the perspective of a developer of services. Who wants to re-invent the wheel and have to write recovery code in the service if you can get it for free. Plus it allows the recovery to be reconfigured as an IT task as opposed to rebuilding the software.

8.6.1 ResetFailedCounterAfter

Specifies the length of the period (in seconds) with no failures after which the failure count should be reset to 0 (zero). If you want to reset the counters you can set to zero which will cause the counters to reset after each failure.

Listing 8.6.1.1 Set ResetFailedCounterAfter programmatically

C#
[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);
    }
}

Listing 8.6.1.2 Set ResetFailedCounterAfter via ChoServiceInstallerSettings.xml file

Open ChoServiceInstallerSettings.xml file, specify value in seconds in 'resetFailedCounterAfter' attribute.

XML
<?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

Specifies the failure action to the service as to restart. The service will restart automatically after the specified period (in min) of time lapsed.

Listing 8.6.2.1 Set RestartService programmatically

C#
[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);
    }
}

Listing 8.6.2.2 Set RestartService via ChoServiceInstallerSettings.xml file

Open ChoServiceInstallerSettings.xml file, specify 'restart/600000' in 'actions' element.

XML
<?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

Specifies the failure action to the service as to reboot the system. SCM will reboot the system automatically after the specified period (in min) of time lapsed.

Listing 8.6.4.1 Set RunProgram programmatically

C#
[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.");
    }
}

Listing 8.6.4.2 Set RunProgram via ChoServiceInstallerSettings.xml file

Open ChoServiceInstallerSettings.xml file, specify 'reboot/600000' in 'actions' element and specify 'Service down.' to 'rebootMessage' element.

XML
<?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

Specifies the failure action to the service as to run a specified program. SCM will start the specified program automatically after the specified period (in min) of time lapsed.

Listing 8.6.3.1 Set RunProgram programmatically

C#
[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");
    }
}

Listing 8.6.3.2 Set RunProgram via ChoServiceInstallerSettings.xml file

Open ChoServiceInstallerSettings.xml file, specify 'run/600000' in 'actions' element and specify 'Notepad.exe C:\sample.txt' to 'command' element.

XML
<?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>

Please bookmark this article as more updates will come shortly.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)