10 minute read

When you are developing server side components using .NET framework, you would either end up having a IIS hosted component (a website, WAS, Web Services (REST/SOAP/JSON, etc), HTTP Handlers, and alike) or a Windows Service for long running tasks or WCF-based services, or a scheduler task for trigger/time oriented tasks.  If the target deployment is IIS based deployment, IIS host manager takes care of the processes of hosting, application pool recycling, memory management, isolation, etc.  With Windows Service, the service console provides hosting capabilities and leaves the process of memory management to the Garbage Collector.  In addition, a very small part of the hosting process is configurable.   With the open source framework XecMe, the process of hosting a Windows Service, execution, CPU utilization, memory management can be eased and made configurable.  This post highlights how to create a Windows Service using XecMe framework and host it using command line arguments.

What is XecMe?

XecMe is an abbreviation for Execute Me.  It is an application block that provides a methodology and framework for executions and hosting batches, background processes and Windows Services.  It is a highly configurable and extensible framework and is built on the principles of task oriented design approach for solving the business problem.  XecMe also works well when integrated with Microsoft Azure in Worker Role.

At the moment, Nuget has a version that works great with .NET 4.0.  But if you are looking for .NET 4.5, you can download the source code from Codeplex and change the target .NET framework.   This framework can be best used for

  • Long running tasks
  • Windows Services
  • Azure Worker Role
  • Event based tasks
  • Context based tasks
  • Batch Processes

All these tasks are configurable and their behavior can be controlled easily by changing parameters in the configuration.

Download the latest binaries

If you are using VS2013, you can use the Package Manager to download the libraries directly or you can manually download them from XecMe On CodePlex.

image

This will create a packages.config with XecMe reference like,

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <packages>
  3.   <package id="XecMe" version="1.0.0" targetFramework="net40" />
  4. </packages>

Understanding XecMe Libaries

 

There are three binary (DLL) files that will be added in your project (Class Library, Azure Worker Role, Windows Service, Website, etc).

  • XecMe.Core.dll – As the name suggests, this library consists of classes that serve core functionalities such as hosting services, reading configuration, rule rngine, task manager, task runners (or execution engines) and utilities
  • XecMe.Common.dll – This library supports the core library by providing functionalities such as argument parsers, reflection utilities, translation provider and most importantly CPU usage limiter
  • XecMe.Configuration.dll – This library also supports core library by providing extension methods and parsers for configuration management

Creating a Windows Service

 

The first step to developing Windows Service is to first start defining a task that can be translated to a Windows Service.   Once you have done that, you can create one or multiple Windows Services in a class library.  Let's say one of the service name is LongRunningTaskAsService.  This class needs to be inherited from XecMe.Core.Services.IService interface as shown below.  Just like you implement any other Windows Service, you can define your code in common methods such as OnStart, OnPause, OnContinue, OnStop. However, there is an additional method OnShutdown which is called just before the service stops.

 

  1. using System;
  2. using XecMe.Core.Services;
  3. using System.Threading;
  4.  
  5. namespace XecMeSamples
  6. {
  7.     public class LongRunningTaskAsService : IService
  8.     {
  9.         private string _serviceName = "LongRuninngTaskAsService";
  10.         private Thread _thread;
  11.         private ManualResetEvent _shutdownEvent;
  12.  
  13.         public bool CanPauseAndContinue
  14.         {
  15.             get { return false; }
  16.         }
  17.  
  18.         public void OnContinue()
  19.         {
  20.             throw new NotSupportedException();
  21.         }
  22.  
  23.         public void OnPause()
  24.         {
  25.             throw new NotSupportedException();
  26.         }
  27.  
  28.         public void OnShutdown()
  29.         {
  30.             _shutdownEvent.Set();
  31.         }
  32.  
  33.         public void OnStart()
  34.         {
  35.             _thread = new Thread(RunInBackground)
  36.                 {
  37.                     Name = "Worker Thread",
  38.                     IsBackground = true
  39.                 };
  40.  
  41.             _shutdownEvent = new ManualResetEvent(false);
  42.             _thread.Start();
  43.         }
  44.  
  45.         private void RunInBackground()
  46.         {
  47.             // run some thing in background
  48.             while (!_shutdownEvent.WaitOne(0))
  49.             {
  50.                 // Replace the Sleep() call with the work you need to do
  51.                 Thread.Sleep(1000);
  52.             }
  53.         }
  54.  
  55.         public void OnStop()
  56.         {
  57.             if (!_thread.Join(3000))
  58.             {
  59.                 // give the thread 3 seconds to stop
  60.                 _thread.Abort();
  61.             }
  62.         }
  63.  
  64.         public string ServiceName
  65.         {
  66.             get { return _serviceName; }
  67.             set { _serviceName = value; }
  68.         }
  69.     }
  70. }

Configuration

 

Each service requires a configuration files.  This configuration file should contain XecMe settings along with application settings.  In the above case, since we have 2 services we will have 2 configuration files as shown in the Solution Explorer.

image

A sample configuration (for LongRunningTaskAsService) would appear like,

  1. <?xml version="1.0"?>
  2. <configuration>
  3.   <configSections>
  4.     <section name="xecMe.Core" type="XecMe.Configuration.XecMeSectionGroup, XecMe.Configuration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e34de6d98c38471a" />
  5.   </configSections>
  6.   <xecMe.Core>
  7.     <extensions>
  8.       <settings>
  9.         <add name="IService" type="XecMeSamples.LongRunningTaskAsService, XecMeSamples"/>
  10.       </settings>
  11.     </extensions>
  12.   </xecMe.Core>
  13. </configuration>

Service Installation

 

XecMeHost.exe acts as a service host and installer. So when you execute a the command below, the service will be installed on the target machine with appropriate settings.  So first thing to remember is to put all assemblies (XecMe DLLs and XecMeHost and your application assemblies) in one folder (from where the service has to be executed).   Alternatively, you can register all XecMe DLLs in GAC and keep only XecMeHost and your application assemblies in that folder

image

You will require administrative rights to perform this action if your OS supports UAC so you may require to run Command Prompt as an Administrator to avoid any errors.  Once you have done this, you can execute the following command

XecMeHost.exe -i -n="LongRunningTaskAsService"
-p="C:\ShortFolder"
-c="C:\ShortFolder\Config\LongRunningTaskAsService.config"
-cpu=50
-a=LocalService
-m=Automatic
-v

Let’s understand the syntax

image

This will install the service on your machine

image

Testing your Windows Service

You can navigate to Service Console to Start the service and test it.  If it fails to start for any reason, you can view the properties of the service to get the executable path and execute the executable path on DOS prompt.

image

For above service the path to executable is:

"C:\ShortFolder\XecMeHost.exe" -s  -p="C:\ShortFolder" -c="C:\ShortFolder\Config\LongRunningTaskAsService.config" -n="LongRunningTaskAsService"

If there are any configuration or start up issues, they will visible on the command prompt

Uninstalling your Windows Service

You can uninstall a Windows Service using Service Controller

installutil /u <servicename>
sc delete <servicename>

Or use XecMeHost like

XecMeHost  /u -n=LongRunningTaskAsService

Source Code

 

Download the source code :