How to send a custom command to a .NET windows Service from .NET code?
Solution 1
You can send "commands" to a service using ServiceController.ExecuteCommand:
const int SmartRestart = 222;
var service = new System.ServiceProcess.ServiceController("MyService");
service.ExecuteCommand(SmartRestart);
service.WaitForStatus(ServiceControllerStatus.Running, timeout);
You'll need to add a Reference to the System.ServiceProcess.dll assembly.
The service can react to the command by overriding ServiceBase.OnCustomCommand:
protected override void OnCustomCommand(int command)
{
if (command == SmartRestart)
{
// ...
}
}
Solution 2
The usual means of communicating with external processes in windows are:
- Named pipes
- Sockets
- COM's GetObject to get a reference to an object and then calling its methods over the exposed interface.
The first two have been exposed as WCF so that is the way to go. Third one does not seem relevant to your situation and is old.
If you need to run your commands from the same machine you can use named pipes but hardening has made it very difficult and troublesome. Otherwise use WCF's TCP named binding.
Comments
-
Hamish Grubijan almost 2 years
As in the following link, one can stop, start, and "stop, then start" a service using C# code.
http://www.csharp-examples.net/restart-windows-service/
I have baked a .NET service that does implement
OnStart
andOnStop
. However, I need to implement a "smart restart" functionality which is more involved than just stopping and then starting. I need to keep the downtime to just a few seconds if that (but Stop + Start can take minutes in this case when done cleanly, and I must do it cleanly), and having some parts of the system available while others are rebooting/refreshing.Long story short - before I jump into implementing this
OnSmartRestart
functionality, I want to make sure that there is a fairly easy way to invoke this call from another C# application.This feature is important, but dangerous. I want to make it fairly hidden, somewhat secure, also keep it simple, and make sure that this has negligible effect on the performance of my Windows service while it is performing its regular chores and not rebooting.
If I have to poll for some file or open a port and spend too much CPU on doing that, it would not be a good solution. I also want to keep this AS SIMPLE AS POSSIBLE (sorry for repetition).
-
Mesh over 11 yearsSome extra info: the DOS SC.exe command can send these commands too, security permissions allowing...e.g. 'SC CONTROL YOURSERVICENAME 200'
-
Sam Axe over 10 yearsThis answer is superior (and required) if you plan on sending parameters.
-
MacGyver over 8 yearsAdrian, how is it normally called using the command, if your method is an alternative? Is "200" in your command analogous to 222 in the source code above?
-
Chris Moschini about 8 yearsNote that this requires special permissions in a typical Server environment where your .Net app/site is running on its own, limited permissions user. You can solve that by giving that user the permission to send custom commands to just this one service using this method: i.imgur.com/tql3pUA.png superuser.com/a/315709/101698
-
ZX9 over 7 yearsIn general, this answer seems superior for any case where you want to take commands from a "userland" app, which seems to be the case for the OP. Using a WCF service does not require mucking about with permissions, which may be safer and more convenient. There's also an MSDN article on hosting WCF services from a Windows service.
-
brz almost 7 yearsAt first this didn't work for me. Then I figured out the command integer must be between 128 and 255... (as stated on the MSDN page). Save yourself a headache and keep this in mind.