Introduction
In this article, I would like to bring you a Windows Service Hosting application aka ChoServiceHost. It simplifies the development of windows service application. No need to worry about all the house keeping works required to create, setup and run the windows services.
There are plenty of articles and samples on the internet on how to write one and install them. Please see the below articles for quick start of developing Windows Service applications
http://blogs.msdn.com/bclteam/archive/2005/03/15/396428.aspx
http://www.codeproject.com/KB/dotnet/simplewindowsservice.aspx
But all them requires the below basic steps in order to create a new Windows Service application
- Creating a ServiceBase
- Creating an Installer
- Installing your new service
- Starting the service
- Most of all, Installing service on a specific account would require you either harcode them in the code or while installing you have input them interactively.
ChoServiceHost application bundled and abstracted all these steps for you. All you have to do is to create a project from 'ChoServiceHost Project' template, overrides few methods like OnStart / OnStop service events and and drop the assembly to 'ChoServiceHost' folder. That's it, your service is ready to use.
PS: Please turn on Reflection Permission in order to use this application.
How to Create Windows Service with ChoServiceHost in a snap...
- Download and extract ChoServiceHostSetup.zip file.
- Run ChoServiceHostSetup.msi file. This will install the ChoServiceHost, Visual Studio templates into your machine.
- Open VS.NET 2008, Create a new project from 'ChoServiceHost Project' template as shown below
-
- It will create a new project with necessary references, classes for you.
-
- Add your business logics or override appropriate members, build the solution.
- Now your Windows service application is ready to use.
- Goto binary folder, you can install and run your service by running ChoServiceHost.exe file using the following command line arguments.
- /i - To install the Windows Service
- /u - To uninstall the Windows Service
- /c - To run your service in console mode.
- /g - To generate key/vector values for encryption (used for password encryption, will talk about it later).
- /e value - To encrypt the passed value and display it on the console.
- /d value - To decrypt the passed value and display it on the console.
1. Additional information when you implement your service class
- ChoServiceApplicationAttribute exposes the below members to control the service parameters. These values used by ChoServiceHost while installing the service.
- ServiceName - Windows Service Name
- ServiceDisplayName - Windows Service Display Name
- ServiceDescription - Short description about Windows Service
- ServiceStartMode - Automatic/Manual/Disabled
- ServiceAccount - It could have one these values LocalService/NetworkService/LocalSystem/User.
- UserName - UserName of Windows account, when you want to run your service under specific user account. This value will be ignored when ServiceAccount is not specified as User.
- EncryptedPassword - User's password in encrypted form. Please refer next section on how to generate encrypted password. This value will be ignored when ServiceAccount is not specified as User.
- Also you class must derive from ChoServiceBase, override the nessasary methods. ChoServiceBase exposes the below overrides
- OnStart - This method called when the Start command sent to the service by SCM or when the OS starts. Usually all the initialization tasks/code should be done here.ation tasks/code should be done here.
- OnStop - This method called when the Stop command sent to the service by SCM. Usually all the cleanup tasks/code should done here.
- OnContinue - This method called when the Continue command to the service by SCM.
- OnPause - This method called when the Pause command to the service by SCM.
- OnShutdown - This method called when the system is shutting down.
- OnSessionChange - This method executed when a change event is received from a Terminal Server session.
- OnPowerEvent - This method executed when the computer's power status has changed.
- OnCustomCommand - This method called when SCM passes a custom command to the service.
- Please check MSDN for System.ServiceProcess.ServiceBase for detailed information about the above commands.
2. How you can control your Windows Service through configuration
After you create the service assembly, literally you can control most of Windows service parameters through configuration. As you know that you can input most of the service level parameters using ChoServiceApplicationAttribute with your class while developing the service. But those values can be overriden and confgured through configuration. In this section, I'll give you brief overview of how to control the windows service through configuration
a. choCommon/applicationSettings
This is the application level settings, In this configuration section, you can specify two parameters
- applicationName - If you are developing and running multiple Windows services using ChoServiceHost.exe, you may want to distinguish them by specifying custom applicattionName. The log files are created by this name. If you dont specifiy this attribute, executable name (ChoServiceHost) will be used.
- eventLogSourceName - This value will be used for posting any messages to the eventlog as the source. If not specified, it uses the applicationName as default value.
b. choCommon/AESCryptoSettings
When you want to run your service under specific user account, you may want protect user's password. This section used for encrypting and decrypting passwords while specifying the service to be run under specific account. Encryption module uses RijndaelManaged symmetric encryption algorithm. In this configuration section, you can specify two parameters
- key - The secret key to be used for the symmetric algorithm
- vector - The IV to be used for the symmetric algorithm.
Do you wonder how to get these values and specified in the configuration section? You can use ChoServiceHost.exe with /g flag. It produces the below in the console as well as in the log file...
2/21/2010 11:23:10 PM, Key: 219097248046007185203210119148228050029042131069242155018049049059100240245094203056187040129069
2/21/2010 11:23:10 PM, Vector: 157038063249122133219020243085077186149245194139
2/21/2010 11:23:10 PM,
2/21/2010 11:23:10 PM, Please copy and paste the below Configuration Entry...
2/21/2010 11:23:10 PM,
2/21/2010 11:23:10 PM, <AESCryptoSettings
type="Cinchoo.Core.Security.Cryptography.ChoAESCryptoGraphySettings, Cinchoo.Core"
key="219097248046007185203210119148228050029042131069242155018049049059100240245094203056187040129069"
vector="157038063249122133219020243085077186149245194139" />
Copy and paste just XML portion to the ChoServiceHost.exe.config file. Now you set the public encryption key in the application. Next you want to encrypt the password by running 'ChoServiceHost /e SomePassword'. This will output values to console as well as log file as below
2/21/2010 11:29:09 PM, Encrypt: SomePassword => 133204048034017206003220050187207208061110033184
Copy and paste just value after => symbol, no spaces, to either ChoServiceApplicationAttribute as below or you can configured in the configuration file as in mentioned in the next section.
1 [ChoServiceApplication("TestService",
ServiceDescription="Test Windows Service", UserName=".\XXX",
EncryptedPassword="133204048034017206003220050187207208061110033184")]
2 public class SampleService : ChoServiceBase
3 {
4 public override void OnStart(ChoServiceHostService serviceBase, string[] args)
5 {
6
7 Console.WriteLine("OnStart");
8 Trace.WriteLineIf(true, "OnStart");
9 base.OnStart(serviceBase, args);
10 }
11
12 public override void OnStop(ChoServiceHostService serviceBase)
13 {
14
15 Console.WriteLine("OnStop");
16 Trace.WriteLineIf(true, "OnStop");
17 base.OnStop(serviceBase);
18 }
19 }
c. choServiceHost/installerSettings
This is the section where you can configure service level atributes. These values overrides any values specified in the ChoServiceApplicationAttribute when you implement your class.
- serviceName - Windows Service Name
- serviceDisplayName - Windows Service Display Name
- serviceDescription - Short description about Windows Service
- serviceStartMode - Automatic/Manual/Disabled
- serviceAccountInfo/serviceAccount - It could have one these values LocalService/NetworkService/LocalSystem/User.
- serviceAccountInfo/userName - UserName of Windows account, when you want to run your service under specific user account. This value will be ignored when ServiceAccount is not specified as User.
- serviceAccountInfo/encryptedPassword - User's password in encrypted form. Please refer the above section on how to generate encrypted password. This value will be ignored when ServiceAccount is not specified as User.
Normally ChoServiceHost discover Service Assembly in their folder/sub-folders and use them by default. But in some situations (you have a service assembly or multiple service assemblies having classes decorated with ChoServiceApplicationAttribute), you may want specify them explicitly. You can do installerSettings/serviceApplicationType element as below
<installerSettings type="Cinchoo.Core.ServiceHost.Settings.ChoServiceHostInstallerSettings, Cinchoo.Core.ServiceHost">
serviceName="TestService" serviceDisplayName="TestServiceDisplayName" serviceDescription="Test Service Description"
serviceStartMode="Automatic" >
<serviceAccountInfo serviceAccount="User" userName="xxx" password="12708216311714802120002721920614921505906" />
<!--You can specify explicitly the type of the service implementation assmebly,
otherwise ServiceHost will discover one from its bin directory/sub-directories for one.-->
<serviceApplicationType>TestServiceApplication.SampleService, TestServiceApplication</serviceApplicationType>
</installerSettings>
d. choServiceHost/settings
Somtime you may want to control the ServiceBase settings through configuration. It is highly unlikely you will configure. In case you want, please read this section.
- autoLog - Indicates whether to report Start, Stop, Pause, and Continue commands in the event log.
- canHandlePowerEvent - A value indicating whether the service can handle notifications of computer power status changes.
- canHandleSessionChangeEvent - A value that indicates whether the service can handle session change events received from a Terminal Server session.
- canPauseAndContinue - A value indicating whether the service can be paused and resumed.
- canShutdown - A value indicating whether the service should be notified when the system is shutting down.
- canStop - A value indicating whether the service can be stopped once it has started.
- ExitCode - The exit code for the service.
- canRaiseEvents - A value indicating whether the component can raise an event.
Please visit MSDN for System.ServiceProcess.ServiceBase to get more information on the above members.
3. Log files
ChoServiceHost produces two log files along other than writing messages event log.
- Log - Log files are created under this folder. These log files are rolled and created new each time the service gets re-started. Use System.Diagnostics.Trace class for writing your debug messages to this log file. You can control the output of these messages by adding the below configuration section in ChoServiceHost.exe.config file. Please visit http://msdn.microsoft.com/en-us/library/system.diagnostics.traceswitch.aspx link for more information.
<!-- Trace Settings -->
<system.diagnostics>
<switches>
<add name="ChoSwitch" value="4" />
</switches>
</system.diagnostics>
- InstallerLog - Log files are created under this folder when you install and uninstall the service. These log files are rolled and created new each time the service gets re-installed. User System.Diagnostics.Trace class to write your debug message to this log file. Whatever you write from IChoServiceProcessInstaller interface overrides will be routed to this log file.For controlling of the output of these message, you need to edit/create InstallUntil.exe.config file, add the above same configuration section.
PS: I'll put a fix on ChoServiceHost to use System.diagnostcs section in ChoServiceHost.exe.config for controlling the output of the InstallerLog debug messages.
4. Subscribe to ServiceProcess Installation events (For advanced users)
For developers who would like to subscribe to ServiceProcess installtion events and to carry out some custom actions, you can do so by deriving you class from IChoServiceProcessInstaller interface.
IChoServiceProcessInstaller interface exposes the below members
- OnCommitting - Method called before the installers in the System.Configuration.Install.Installer.Installers property committ their installations.
- OnCommitted - Method called after all the installers in the System.Configuration.Install.Installer.Installers property have committed their installations.
- OnBeforeUninstall - Method called before the installers in the System.Configuration.Install.Installer.Installers property perform their uninstall operations.
- OnBeforeRollback - Method called before the installers in the System.Configuration.Install.Installer.Installers property are rolled back.
- OnBeforeInstall - Method called before the System.Configuration.Install.Installer.Install method of each installer in the installer collection has run.
- OnAfterUninstall - Method called after all the installers in the System.Configuration.Install.Installer.Installers property perform their uninstallation operations.
- OnAfterRollback - Method called after the installations of all the installers in the System.Configuration.Install.Installer.Installers property are rolled back.
- OnAfterInstall - Method called after the System.Configuration.Install.Installer.Install methods of all the installers in the System.Configuration.Install.Installer.Installers property have run.
Please visit MSDN for System.ServiceProcess.Installer to get more detailed information for the above methods.
Below is the code snippet of implemented IChoServiceProcessInstaller interface
1 [ChoServiceApplication("TestService", ServiceDescription="Test Windows Service",
ServiceStartMode=ServiceStartMode.Automatic)]
2 public class SampleService : ChoServiceBase, IChoServiceProcessInstaller
3 {
4 public override void OnStart(ChoServiceHostService serviceBase, string[] args)
5 {
6
7 Console.WriteLine("OnStart");
8 Trace.WriteLineIf(true, "OnStart");
9 base.OnStart(serviceBase, args);
10 }
11
12 public override void OnStop(ChoServiceHostService serviceBase)
13 {
14
15 Console.WriteLine("OnStop");
16 Trace.WriteLineIf(true, "OnStop");
17 base.OnStop(serviceBase);
18 }
19
20 #region IChoServiceProcessInstaller Members
21
22 public void OnCommitting(ServiceProcessInstaller serviceProcessInstaller,
System.Configuration.Install.InstallEventArgs e)
23 {
24 Trace.WriteLineIf(true, "OnCommitting");
25 }
26
27 public void OnCommitted(ServiceProcessInstaller serviceProcessInstaller,
System.Configuration.Install.InstallEventArgs e)
28 {
29 Trace.WriteLineIf(true, "OnCommitted");
30 }
31
32 public void OnBeforeUninstall(ServiceProcessInstaller serviceProcessInstaller,
System.Configuration.Install.InstallEventArgs e)
33 {
34 Trace.WriteLineIf(true, "OnBeforeUninstall");
35 }
36
37 public void OnBeforeRollback(ServiceProcessInstaller serviceProcessInstaller,
System.Configuration.Install.InstallEventArgs e)
38 {
39 Trace.WriteLineIf(true, "OnBeforeRollback");
40 }
41
42 public void OnBeforeInstall(ServiceProcessInstaller serviceProcessInstaller,
System.Configuration.Install.InstallEventArgs e)
43 {
44 Trace.WriteLineIf(true, "OnBeforeInstall");
45 }
46
47 public void OnAfterUninstall(ServiceProcessInstaller serviceProcessInstaller,
System.Configuration.Install.InstallEventArgs e)
48 {
49 Trace.WriteLineIf(true, "OnAfterUninstall");
50 }
51
52 public void OnAfterRollback(ServiceProcessInstaller serviceProcessInstaller,
System.Configuration.Install.InstallEventArgs e)
53 {
54 Trace.WriteLineIf(true, "OnAfterRollback");
55 }
56
57 public void OnAfterInstall(ServiceProcessInstaller serviceProcessInstaller,
System.Configuration.Install.InstallEventArgs e)
58 {
59 Trace.WriteLineIf(true, "OnAfterInstall");
60 }
61
62 #endregion
63 }
That's all folks. Try it, please do drop your feedback.
Updated
ChoServiceHost binary and source files are updated with the below fixes.
- Added volatile keyword to ChoSingleton._instance member.
- There was a glitch in log files generation by Service Installer. Addressed the issue. Now the ChoServiceHost produces the number of log folders based on the run mode
-
- ConsoleLog - Log files are created under this folder when you run ChoServiceHost in console mode (ChoServiceHost.exe /c).
- InstallServiceLog - Log files are created under this folder when you install the service (ChoServiceHost.exe /i).
- ServiceInstallerLog - Log files are created under this folder by Windows Service Installer (Whatever traces written from IChoServiceProcessInstaller overrides).
- ServiceLog - Log files are created under this folder when the Service gets started successfully (Whatever traces written from ChoServiceBase overrides).
- UninstallServiceLog - Log files are created under this folder when you uninstall the service (ChoServiceHost.exe /u).
Still to come:
- Multiple service host assemblies hosted and run in one process (different AppDomains though)
- Adding recovery options to Windows Service
- Adding Dependency services to your Windows Service application
- more