Service handling in MSBuild – ServiceController tasks

There is always a time, in configuring and setting up deployment with MSBuild, when you want to start and stop services on a specific machine. You could always run the sc command from an Exec task. But there must be a better way, an of course there is. For most things you need to do in MSBuild there seem to be a task for it in the MSBuild community task library.

So while poking around I find a couple of gems, ServiceQuery and ServiceController. Both are powerful tools in MSBuild deployment and works both locally and remote. The only problem is that the documentation is quite sparse, especially when handling remote services. So I Just figure I write down what I did to get it working in my scripts.

A little background: a web project that should be deployed to different sites, test, stage and production. The stage and production is redundant with clustering so its really stable, but need some extra attention for each node to be updated. You shut down one node, shut down the IIS and state services, clean out a few folders and then update with new web and finish up starting it all up again.

So to the script, add the community tasks to the script, go on with setting up some default properties and some paths and create a default target. After this you are ready to start and stop services:



You see the basic structure here, shut down, call a separate MSBuild file that do the actual file copying the start up the services as well, and finally do a smoke test to test that the site is up and running again.

Next we see the actual shutdown part, first we do a ServiceQuery to check if there in fact is a SMTP service, if it reports other than Unknown, the service is in place. This makes it possible to do a conditional shutdown. The MachineName attribute is of course for remote shut down but works on localhost as well, making it possible to have the same script for local and remote handling. Make sure that the account that the TeamCity agent is running under, have access to perform shutdown/startup on the remote machine. Now we can go ahead and shut down the services:


The actual deployments of the files are easy, you can just perform a copy task, as in the remote service handling, make sure you have access to the folder on the remote machine you are deploying to. After the deployment we do the Start action on each of the services we want to start up. Last, we do the smoke test. To do this we can use the task WebDownload, we just specify the URL and an output file and this step will fail if you don’t get any access. The other benefit is that you kick the first time JIT compilation here.


Now go deploy something!


PS: I have previously run a series on TeamCity and MSBuild in my private blog so if you are interested to learn more go ahead and read:

Artifact handling in TeamCity 4.0

Deploy with MSBuild and custom targets part 1

Deploy with MSBuild and custom targets part 2

Version handling in TeamCity part 1

Version handling in TeamCity part 2

This Post Has 3 Comments

  1. Sebastián

    Great post! It’s really helpful, you saved me a lot of time :-)

    Keep up the good work!

  2. pre

    I use vs 2008, .net 3.5, winxp client, win2003 server, IIS 6.0, msbuild.

    Key for me:

    Using MSBuild Extension Pack or Community tasks., how can I know the status/state (Started, Stopped, …) of WebSite or AppPool (IIS6) ??

    Iis6WebSite and IIs6AppPool (and future for IIS7), do wait for stopped status when try Stop WebSite or AppPool ?

  3. Richard

    Very useful post. The amount of builds that fail due to trying to uninstall a service that is running, and quite possibly executing something, was getting ridiculous. This has put that to rest.

Leave a Reply