18

I'm writing a series of Windows services. I want them to fail if errors are thrown during startup (in OnStart() method). I had assumed that merely throwing an error in OnStart() would do this, but I'm finding that instead it "Starts" and presents me with a message stating "The service has started, but is inactive. Is this correct?" (Paraphrase). How do I handle the error so it actually fails to start the service?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
C. Ross
  • 31,137
  • 42
  • 147
  • 238

3 Answers3

17

If the main thing you want is for the Services window to report that there was an error, from what I've tried (.NET3.5 on Windows 7), the only way to do this is by setting the ExitCode. I recommend setting it to 13816, since this results in the message, "An unknown error has occurred." See the windows error codes.

The sample below accomplishes three things.

  1. Setting ExitCode results in a useful message for the end-user. It doesn't affect the Windows Application log but does include a message in the System log.
  2. Calling Stop results in a "Service successfully stopped" message in the Application log.

  3. throwing the exception results in a useful log entry in the Application log.

protected override void OnStart(string[] args) {
    try {
        // Start your service
    }catch (Exception ex) {
        // Log exception
        this.ExitCode = 13816;
        this.Stop();
        throw;
    }  
}
DarkBee
  • 16,592
  • 6
  • 46
  • 58
Sean
  • 8,407
  • 3
  • 31
  • 33
  • 1
    13816 is labeled as an IPSEC error so it doesn't exactly apply, but any non-zero int is considered an error by the Service Control Manager. I believe the meaning of the code is up to the service itself. – xr280xr Dec 13 '13 at 20:45
  • 2
    That's a very good point. Perhaps, code 1064 would be better. (ERROR_EXCEPTION_IN_SERVICE - An exception occurred in the service when handling the control request.) The main idea for me is displaying a message to the user that is somewhat helpful, and especially not misleading. – Sean Dec 14 '13 at 00:19
  • 1
    The key parts are setting the ExitCode and the throw. There's no need for the `Stop();` - the exception handler in ServiceBase does this. – Rhys Jones Jul 15 '16 at 09:31
8

if you are running .NET 2.0 or higher, you can use ServiceBase.Stop to stop the service from OnStart. Otherwise call Stop from a new thread.

ref [devnewsgroups] (http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework/topic50404.aspx)

(news group gone)

Steven A. Lowe
  • 60,273
  • 18
  • 132
  • 202
7

Move all of your startup logic to a separate method, and Throw exceptions (or call OnStop) from that seperate method.

OnStart has some oddities when starting up. I have found that if OnStart() has no more than one line in it, then I dont get the "The service started and then stopped.Some services stop automatically if they have no work to do" message, and thrown exceptions will terminate the process and log to the app event log.

Also with the seperate startup method, you can use a technique like this to debug it without attaching. http://www.codeproject.com/KB/dotnet/DebugWinServices.aspx

Jeff Atwood
  • 63,320
  • 48
  • 150
  • 153
StingyJack
  • 19,041
  • 10
  • 63
  • 122