views:

991

answers:

5

I have a service application written in C# and under certain circumstances, I would like it to terminate itself. This would happen after the service has been running for a while, so this would not be happening in the OnStart() event.

Everything that I have read so far suggests that the only safe way to terminate a service is through the Service Control Manager. My service runs as Local Service and does not have the rights to start or stop services, so I can't access the SCM from the service itself. Is there another way to self-terminate while still playing by the rules of the SCM?

+15  A: 

Try ServiceBase.Stop().

configurator
+3  A: 

What happens if you just let all the executing threads finish? I can imagine three possible outcomes:

  • The SCM notices, and decides you finished appropriately
  • The SCM notices, thinks you died, and restarts you
  • The SCM doesn't notice, and shows you as still running

EDIT: I suspect this answer is the best one really, but I'll leave this up (for the moment) just for the sake of interest.

Jon Skeet
I believe the first outcome is the right one. But how do you achieve that? The main thread is a message-loop created by the ServiceBase, (ServiceBase.Run(service) never returns). The way to cause the Run() call to return is to call service.Stop() - Like Application.Exit exits after Application.Run.
configurator
It's been quite a long time since I wrote a Windows Service, but I don't remember it running a message loop for me. Hmm. Must just be my bad memory...
Jon Skeet
Of course, I could be wrong. I don't write Services that much... I'll look into it though.
configurator
It's not a message loop. The Service Control Manager puts the main thread into a wait state and wakes it to call the control handler callbacks. When all the services in the process have stopped it is released and the ServiceBase.Run method returns.
Stephen Martin
What's the difference between that and a message loop? Windows Forms processes wait until there's a callback, and Windows Services wait until there's a callback. Is there any difference other than the terminology?
configurator
Your third option is what happens. The infrastructure necessary for the Service Control manager to monitor the service for all calls to set up timers, completion ports, queued callbacks, etc. would be onerous, if even possible. So it is not setup to stop a service even if it has no active threads.
Stephen Martin
A message loop is a well defined term for Windows programming it involves a thread that actively removes items from the message queue, processes them and then requests another. What the SCM does with the processes main thread is qualitatively different.
Stephen Martin
Ok. I don't presume to know how processes work internally. I've only written one or two small-utility-meant-for-one-machine sort of things...The third option does happen. Also, when trying to stop the service normally after the process, you get an error because 'the process ended abnormally'.
configurator
A: 

Don't have the service run under Local Service. Have it run under a user that has the rights to stop a service.

Although the idea of self-terminating services is not the best of ideas. That very fact alone means that it should be an application, and not a service.

casperOne
I disagree - I could imagine a server of some description (like a web service, but not running under IIS) with an admin panel including "stop".
Jon Skeet
@Jon: shouldn't that admin panel in your example run as its own application, one with the rights to stop - and start - a service?
configurator
I'm with Jon on this. The admin panel might not be on the same machine; it might not even be on Windows.
jdigital
@Jon: That could be the case (and there are products that do this), but in that case, it is a function of the user running the admin panel, and they should send the signal to the SCM to stop the service, not to the service itself to stop itself.
casperOne
@jddigital: See my respond to Jon's comment. Additionally, it can be a security issue, because then you can give people with access to the service the right to shut it down, when they normally don't have rights to do so.
casperOne
Like casperOne said. Local Service is there for a reason...
configurator
+1  A: 

An interesting side note, but in Windows 7, services will be able to control when they start too.

Drew Noakes
A: 

If you want to terminate the service instead of stopping it (perhaps because the service has caught an otherwise unhandled exception) you can use Environment.Exit(1) (use another exit code if you want).

Windows will discover that the service has terminated unexpectedly. If the service has been configured to recover the recovery procedure will be used which includes options for restarting the service, running a program or restarting the computer.

Martin Liversage