I’ve been revisiting a POC I did a while back that involved some custom Windows Service development. It reminded me that it’s a little bit of a pain managing the clean and deployment of your Windows Services as part of your MsBuild script and I just wanted to make a few notes on this as a reminder to myself and potentially help others. The below will describe what I do.
Cleaning up
Typically this is the section that causes some hassle. The aim is to undeploy and delete any previous instances of the windows service and return the machine to a clean state before your build creates the system again. To keep it easy I have used the continue on error flag so if the services do not exist already the build will just continue (you could add stuff to check for the existence of the service). Often some of the problems I have had in the past here relate to the service being marked for deletion and not actually being deleted. The tasks I use in my script seem to deal with most occurances of that.
You can see in my below sample that I have 2 Windows services that I’m working with. The first thing I do is to use the SC command to stop the service. I then use the taskkill command to force it to kill the process if it hasn’t been stopped yet. If you want a more elegant approach here you could probably create a custom task to wait until the service has stopped and then kill if it hasn’t stopped within a certain time.
In my case I don’t care about it being elegantly closed down as it’s a development environment and I just want to get rid of the services.
After stopping and killing the service I then use the SC command to delete the service.
I could have used InstallUtil to uninstall the service rather than SC deleting it but in practice I seemed to have more occurances of the service being marked for deletion. If you get problems like this Avner wrote a quite useful post about this where he suggests some causes. The most common causes seem to be:
- MMC being open and holding a reference to the service
- The process is still running and your stop command didn’t stop before the timeout (hence use of task kill above)
Deploying Windows Services
When it comes to deploying the services later in the MsBuild script after my code changes have been compiled I use InstallUtil to install my service. One point to note here is that if you specify to have a user account as the service credential then it will prompt you for the credentials which isn’t very useful for an automated build script. I’ve seen some articles describing writing a custom installer so you can supply credentials from the command line which the custom installer will handle, but lets keep it simple. In my C# project I specified the installer to use the Local Service account and then after than in the below sample you can see how I use SC to configure the windows service to use the credentials and properties I want it to use.
Starting Windows Services
Finally before I start running some testing I want to make sure that my services are up and running so I use the SC command to start the services.
Summary
This approach while a little bit crude seems to be quite effective at managing the windows services in my MsBuild script and I haven’t had to deal with the hassle they had been causing me. There seems to be forum posts discussing different problems people have had but I didn’t come across anything which describes the overall approach like I’ve tried to do above so hopefully this is useful.