Using Custom Commands with Windows Services and PowerShell

A feature I recently came across when reading through the MSDN documentation was the ability to implement “custom commands” for windows services.  After reading about it, I wish I would have known about it sooner.

A custom command is a way to essentially send a signal to a service that you want it to process a command.  The command can be any integer from 128 to 255, but has no parameters, and returns no value.

There are a few situations where I immediately thought this may be useful.

1. A service health check.  I’ve seen in several scenarios in the past where at definite intervals a windows service will do something to say it is still alive.  This could be used to immediately force the service to do a health check, log out to a file, etc.

2. A service wake up.  For some windows services, they will just poll some sort of queue to see if work is available.  If it is not they will sleep for a given amount of time.  While this works, if someone is trying to get something done, the service may not respond to the request for due to the wait time.  Implementing a command to wake up the service could have it check the queue for work to process immediately.

Implementing a custom command on a service is very simple.  In a service class that inherits from ServiceBase, simply override the OnCustomCommand method.

Here’s a very simple bit sample code I wrote to demonstrate this functionality.

public enum CustomCommands
{
    WakeUp = 128,
}

private void Log(string text)
{
    File.AppendAllLines("C:\\wakeupservice.log", new[] { string.Format("[{0:yyyy-MM-dd HH:mm:ss}] - {1}", DateTime.Now, text) });
}

protected override void OnCustomCommand(int command)
{
    switch ((CustomCommands)command)
    {
        case CustomCommands.WakeUp:
            Log("Wake up!");
            break;
    }
}

Now to actually execute the command.  This can be done through the ServiceController class, or if you prefer to do it through the command line, can be done through PowerShell as well.

(Get-Service "CustomCommandService").Start()
(Get-Service "CustomCommandService").ExecuteCommand(128)
(Get-Service "CustomCommandService").Stop()

My log file now shows the following:

[2013-07-19 23:34:31] - Started!
[2013-07-19 23:35:04] - Wake up!
[2013-07-19 23:35:12] - Stopped!

That’s all there is to this post.  I hope you find this useful!

A full solution is available on my BitBucket samples repository.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s