Friday, February 09, 2007

Dynamically Controlling Windows Services Using SC.exe

There are many instances where you would like to have remote control over Windows Services.  In fact, during deployments, you might want to even have the ability to remove and reinstall Windows Services on the fly, or even go so far as to install multiple copies of the same service under different names and/or configurations.

These requirements go beyond the ability of the native installation procedures that are included with Visual Studio or the framework (such as InstallUtil.exe).  However, with SC.exe, you can have complete control over Windows Services, and even install them with different names and so forth.

SC.exe comes with the Resource Kit and runs from the command line.  It takes a variety of arguments, including a command, the service name, the path to the file, the display name, and the machine to execute against.

sc [Servername] Command Servicename [Optionname= Optionvalue...]

It's important to note that the space after the "=" in the Optionname key value pair DOES exist and is not a typo!  You'll see that in the examples below.  Most of us have a tendency (myself included) to look at that and assume there's no way that the space should be there, but it is.

The servername is optional;  if not provided this will run against the local machine.

There are many commands you can give, but the important ones are:

Start
Starts a service
Stop
Sends a Stop request to a service.

Create
Creates a service (adds it to the registry).
Delete
Deletes a service (from the registry).

It's important to note that the ServiceName here is the actual ServiceName, NOT the Display Name, which is generally what you use when issuing Net Start commands.

So, if we wanted to stop the BlogReaderService on BlogBox1 from BlogBox2, at the command line on BlogBox2 we would enter:

sc BlogBox1 Stop BlogReaderService

There are several options available as well for the executable.  Here are a few of the important ones.

start=boot, system, auto, demand, disabled
Start type for the service. Option values include types used by drivers.
(default = demand)

binPath=(string)
Path name to the service binary file. There is no default for this parameter. This string must be supplied.

DisplayName=(string)
A string that can be used by user-interface programs to identify the service.

So let's assume that during deployment I want to stop, delete, create, and start my BlogReaderService.  My BlogReaderService.exe sits in my c:\temp folder.  I want the BlogReaderService to start automatically, and want its DisplayName to be MyBlogReaderService.  Assuming I am on BlogBox2 and I want this to occur on BlogBox1, the four commands would look like this:

sc BlogBox1 Stop BlogReaderService

sc BlogBox1 Delete BlogReaderService

sc BlogBox1 Create BlogReaderService start= auto binPath= c:\temp\blogreaderservice.exe DisplayName= MyBlogReaderSerivce

sc BlogBox1 Start BlogReaderService

Note the spaces after the "=" in the command line...

Now that I have that, let's assume I have a second copy of blogreaderservice.exe sitting in c:\temp2 with it's own blogreaderservice.exe.config pointed a different datasource.  Now I want to install it, but I need a different service name and display name and start it because the service is already there from the exe in c:\temp.  That command line would look like this.

sc BlogBox1 Create SecondBlogReaderService start= auto binPath= c:\temp2\blogreaderservice.exe DisplayName= MySecondBlogReaderSerivce

sc BlogBox1 Start SecondBlogReaderService

And there you are...two copies of the service installed under different names.

Have fun!

Rob