Windows Service to Host Multiple Processes






3.21/5 (10 votes)
A Windows service which spawns mutiple threads
Introduction
This application framework defines an easy way to host multiple modules (DLLs) in one single Windows service with a single configuration file. This way, a group of services can be packaged as one single Windows service.
Background
Windows services are indispensable for any IT setup. These are used to perform simple to moderately complex tasks. After some time, the list of Windows services start growing and become difficult to maintain. Windows OS has several processes running in svchost.exe. Although third parties can add their processes to run under svchost.exe, I could not find any documentation explaining the steps required to add your custom modules to this process. So I developed an easy framework to run a window service which can host other assemblies (DLLs). New assemblies can be added just by changing the configuration file, no compilation is needed.
Using the Code
To use this framework, you need basic understanding of the following:
System.Configuration
System.Threading
System.Reflection
The app.config file is extensible. Each process assembly can define its own name/value section. First define section group as follows:
// <sectionGroup name="SvcsConfig">
// <section name="TimedActivity"
// type="System.Configuration.NameValueSectionHandler" />
// <section name="WebDownload"
// type="System.Configuration.NameValueSectionHandler" />
// </sectionGroup>
And then the (configuration) section as follows:
// <TimedActivity>
// <add key="Assembly"
// value="c:\work\WinSvcsGroup\TimedActivity\bin\debug\TimedActivity.dll" />
// <add key="Type" value="TimedActivity.WriteTimeToFile" />
// <add key="FileToWrite" value="c:\Demo\TimeOut.txt" />
//</TimedActivity>
//<WebDownload>
// <add key="Assembly"
// value="c:\work\WinSvcsGroup\WebDownload\bin\debug\WebDownload.dll" />
// <add key="Type" value="WebDownload.WebDownload" />
// <add key="Folder" value="c:\Demo\downloads" />
//</WebDownload>
The first two keys Assembly
and Type
are mandatory. These specify name of assembly and class within an assembly that has the entry point for processing. Other additional keys are module specific and can be added, as many as required. The service reads the above information to spawn multiple threads and host different modules.
The custom assemblies, which are built to perform work, need to be inherited from an abstract class WinSvcThread
.
//abstract public class WinSvcThread
//{
// private string section;
// public WinSvcThread(string Section)
// {
// section = "SvcsConfig/" + Section;
// }
// #endregion
// public virtual void Process()
// {
//
// }
// public string Section
// {
// get
// {
// return section;
// }
// }
// }
The derived class needs to define a constructor and override virtual method Process
, which is the entry point for the processing.
To illustrate, in the sample application, there are two assemblies hosted in Windows service WinScvcsHost
. Assembly TimedActivity
writes DateTime.Now
to a text file, and WebDownload
downloads files from a website.
The worker assembly, TimedActivity
is implemented as follows:
//public class WriteTimeToFile : WinSvcThread
//{
// Timer Clock;
// /// <summary>
// /// Constructor. Implement as follows.
// /// </summary>
// /// <param name="str">
// /// sets the configuration section related to this process
// /// </param>
// public WriteTimeToFile(string str)
// : base(str)
// {
// }
// /// <summary>
// /// The entry point for the module.
// /// The business logic for thread should go here.
// /// </summary>
// override public void Process()
// {
// try
// {
// Clock = new Timer();
// // raise event after two minutes.
// Clock.Interval = 1000 * 60 * 2;
// Clock.Start();
// Clock.Elapsed += new ElapsedEventHandler(Timer_Tick);
// }
// catch (Exception es)
// {
// EventLog.WriteEntry("WriteTimeToFile TimerTick ", es.Message);
// }
// }
// public void Timer_Tick(object sender, EventArgs eArgs)
// {
// try
// {
// if (sender == Clock)
// {
// StreamWriter SW;
// NameValueCollection nvc =
// (NameValueCollection)ConfigurationManager.GetSection(base.Section);
// string FileToWrite = nvc["FileToWrite"];
// SW = File.AppendText(FileToWrite);
// SW.WriteLine(DateTime.Now.ToString());
// SW.Close();
// }
// }
// catch (Exception es)
// {
// EventLog.WriteEntry("Timer_Tick ", es.Message);
// }
// }
//}
Advantages
- Since each service runs as a thread, the system resources are conserved.
- It is easy to manage the group rather than several independent services.
- The custom assemblies can each use the App.config.
History
- 10th October, 2006: Initial post