Windows services are handy things to have around. Unfortunately, Microsoft doesn't make it simple to write your own. What is more, they can be difficult to debug during development.
This article presents a simple framework for creating your own Windows services. It accepts several command line parameters to make installing, starting, stopping, and uninstalling the service a snap. Also, it has a console mode to make debugging easy.
I spent a lot of time wading through pages and pages, site after site, of example code for developing Windows services. None of the samples out there really did everything I wanted. Some employed considerable hacks, and there were none that separated the service bits from the actual worker bits. This project contains what I consider to be the bare minimum features for a usable Windows service, with a simple interface for adding your worker code.
Using the Code
This is setup for Visual Studio 2008 and .NET 3.5. Some modifications would be needed to use this code with .NET 2.0, e.g., get rid of lambda functions, but it could easily be done.
All you have to do is inherit the
ISimpleServiceWorker interface and implement it in your worker class.
Initialize your resources in the
Init() method and clean up your resources in the
Cleanup() method. The
Run() method would typically contain a loop that manages the state of your task. You don't have to create a thread; the
SimpleProject class will create the necessary thread. You should keep in mind that the thread will be terminated by the
Thread.Abort() method. The
ThreadAbortException will be caught in the
SimpleProject class that creates the thread context, so you don't need to catch it, but you could if you have a reason. In order to keep the shutdown time reasonable, try not to make blocking calls, e.g., sockets.
Services are notoriously difficult to debug. For this reason, this project provides for a console mode so that you can run your code without all of the service overhead. Simply pass the -console command line switch to your service executable, and Shazaam! You're running in console mode. In console mode, the static
WriteLog method of the
SimpleService class directs logging to the console window instead of the application event log.
Managing Your Service
SimpleService class provides several command line switches:
PS C:\rev\src\simpleservice\src\bin\release> .\SimpleService.exe -help
= SimpleService -install == install service
= SimpleService -uninstall == uninstall service
= SimpleService -start == start service
= SimpleService -stop == stop service
= SimpleService -status == get the current status of the service
= SimpleService -console == run in console mode
= SimpleService -help == show this help message
Using these command line switches, you can install and uninstall your service without using InstallUtil.exe. Also, you can start and stop your service once it is installed. The -status switch will tell you if your service is installed, started, or stopped.
The project uses the process name as the service name. You could change this in code, but you must make sure that the same name is applied to the
ServiceBase and the
ServiceInstaller. For simplicity, use the static
ServiceName property of the
The project assumes that your service needs LocalSystem privileges and starts automatically. This will invoke the Windows Vista and Windows 7 UAC dialogs when you use the service. You can change those defaults in the
m_processInstaller = new ServiceProcessInstaller()
Account = ServiceAccount.LocalSystem
m_serviceInstaller = new ServiceInstaller()
StartType = ServiceStartMode.Automatic,
ServiceName = ServiceName,
DisplayName = ServiceName,
Description = ServicePath
I think you will be pleased with this design. Simply implement a worker class by inheriting the
ISimpleServiceWorker interface, change the project assembly name, and build it! The command line switches make everything else a snap. Please don't hesitate to notify me of bugs or oversights. And by all means, enjoy!
- January 2010 - Initial submission.