Creating the Service
I recently was tasked with writing a Windows Service. I had never done this before but it seemed to me that it couldn't be that difficult. So I did what any good software engineer would do. I fired up Visual Studio 2012, opened my sample solution I use to test code in, and added a new project selecting the Windows Service template.After this new project is created you start out with several files and I quickly realized I should probably read a tutorial on what to do. A quick google search lead me to an MSDN article. After reading through the article and following some links to others I followed the tutorial to create the service.
Debugging the Service
After getting the service created and setting it up to call the classes needed to do the work for the service I had to find a way to debug the service. There are actually two ways to debug the service, one is to create a separate test harness project (I used WinForms) that will just call the classes that are doing the work. You can setup different buttons that will call the different parts and use that for your testing. In order to debug the service in the other way you will have to install it locally on your machine and attach the VS debugger to it. One way to do this more "automatically" is to add the following line where you want to start debugging:Debugger.Break()
It will then show a box asking you what you want to use to debug the service with.
Making the Service Work
When I got to the point of checking to see what I had actually written to was going to work as a service I had a little surprise. When I started my service it would only run the OnStart method once. I had not really thought this through and assume that there would be some form of a quick and easy build-in timer to use. Since this was not the case, I had to do a little searching. The conclusion I came to was there was not one source that gave me a single, good solution.The best solution I was able to put together was to use a System.Threading.Timer. This is a timer on a new thread. I allows you to start the service and check something every x minutes with a timer. When the timer runs you will want to check to make sure that you are not already processing so that you don't process twice at the same time. The OnStop method is written to allow the service 60 seconds to stop processing and doing what it is doing before you just kill the service.
Final Solution
Here's the solution in one chunk of code:public partial class Service : ServiceBase
{
private Main _service = new Main();
private System.Threading.Timer _serviceTimer;
private bool _isRunning = false;
protected override void OnStart(string[] args)
{
//Handles the unhandled things so issues will be logged
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += HandleUnhandledExceptions;
currentDomain.AssemblyResolve += HandleAssemblyResolve;
currentDomain.DomainUnload += HandleDomainUnload;
currentDomain.ProcessExit += HandleProcessExit;
currentDomain.TypeResolve += HandleTypeResolve;
currentDomain.ResourceResolve += HandleResourceResolve;
try
{
//create timer and attach our method delegate to it
System.Threading.TimerCallback timerDelegate = new System.Threading.TimerCallback(DoWork);
_serviceTimer = new System.Threading.Timer(timerDelegate, null, 1000, 300000);
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
}
/// The "timer" thread that gets called
private void DoWork(object state)
{
//only do anything if it is not already running
if (!_isRunning)
{
try
{
//Debugger.Break();
_isRunning = true;
_service.Start();
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
finally
{
_isRunning = false;
}
}
}
protected override void OnStop()
{
//Don't stop while the timer is running or if we have waited 60 seconds
int secondsCounter = 0;
while (_isRunning && secondsCounter <= 60)
{
System.Threading.Thread.Sleep(1000);
secondsCounter++;
}
}
}