Using XecMe to host Windows Services
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.
This will create a packages.config with XecMe reference like,
- <?xml version="1.0" encoding="utf-8"?>
- <packages>
- <package id="XecMe" version="1.0.0" targetFramework="net40" />
- </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.
- using System;
- using XecMe.Core.Services;
- using System.Threading;
- namespace XecMeSamples
- {
- public class LongRunningTaskAsService : IService
- {
- private string _serviceName = "LongRuninngTaskAsService";
- private Thread _thread;
- private ManualResetEvent _shutdownEvent;
- public bool CanPauseAndContinue
- {
- get { return false; }
- }
- public void OnContinue()
- {
- throw new NotSupportedException();
- }
- public void OnPause()
- {
- throw new NotSupportedException();
- }
- public void OnShutdown()
- {
- _shutdownEvent.Set();
- }
- public void OnStart()
- {
- _thread = new Thread(RunInBackground)
- {
- Name = "Worker Thread",
- IsBackground = true
- };
- _shutdownEvent = new ManualResetEvent(false);
- _thread.Start();
- }
- private void RunInBackground()
- {
- // run some thing in background
- while (!_shutdownEvent.WaitOne(0))
- {
- // Replace the Sleep() call with the work you need to do
- Thread.Sleep(1000);
- }
- }
- public void OnStop()
- {
- if (!_thread.Join(3000))
- {
- // give the thread 3 seconds to stop
- _thread.Abort();
- }
- }
- public string ServiceName
- {
- get { return _serviceName; }
- set { _serviceName = value; }
- }
- }
- }
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.
A sample configuration (for LongRunningTaskAsService) would appear like,
- <?xml version="1.0"?>
- <configuration>
- <configSections>
- <section name="xecMe.Core" type="XecMe.Configuration.XecMeSectionGroup, XecMe.Configuration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e34de6d98c38471a" />
- </configSections>
- <xecMe.Core>
- <extensions>
- <settings>
- <add name="IService" type="XecMeSamples.LongRunningTaskAsService, XecMeSamples"/>
- </settings>
- </extensions>
- </xecMe.Core>
- </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
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
This will install the service on your machine
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.
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 :