53
protected override void OnStart(string[] args)
{
    AppDomain.CurrentDomain.UnhandledException +=
        new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

    Thread.Sleep(10000);

    throw new Exception();
}

void CurrentDomain_UnhandledException(object sender,
                                      UnhandledExceptionEventArgs e)
{
}

I attached a debugger to the above code in my windows service, setting a breakpoint in CurrentDomain_UnhandledException, but it was never hit. The exception pops up saying that it is unhandled, and then the service stops. I even tried putting some code in the event handler, in case it was getting optimized away.

Is this not the proper way to set up unhandled exception handling in a windows service?

Jon Seigel
  • 12,251
  • 8
  • 58
  • 92
Mike Pateras
  • 14,715
  • 30
  • 97
  • 137

5 Answers5

62

The reason that the UnhandledException event on the current AppDomain does not fire is how services are executed.

  1. User sends a Start command from the Windows Service Control Manager (SCM).
  2. The command is received by the framework's ServiceBase implementation and dispatched to the OnStart method.
  3. The OnStart method is called.

Any exception which is thrown by OnStart is handled in the base class, logged to the Event Log, and translated into an error status code returned to the SCM. So the exception never propagates to the AppDomain's unhandled exception handler.

I think you would find that an unhandled exception thrown from a worker thread in your service would be caught by the AppDomain's unhandled exception handler.

Palec
  • 12,743
  • 8
  • 69
  • 138
Chris Dickson
  • 11,964
  • 1
  • 39
  • 60
10

In a Windows Service you do NOT want to be running much code in the OnStart method. All you want there is the code to launch your service thread and then return.

If you do that you can handle exceptions that happen in your service thread just fine.

e.g.

public static void Start()
{
    AppDomain currentDomain = AppDomain.CurrentDomain;
    currentDomain.UnhandledException += new UnhandledExceptionEventHandler(currentDomain_UnhandledException);

    running = true;
    ThreadStart ts = new ThreadStart(ServiceThreadBody);
    thread = new Thread(ts);
    thread.Name = "ServiceThread";
    thread.Priority = ThreadPriority.BelowNormal;
    thread.Start();
}
Ian Mercer
  • 38,490
  • 8
  • 97
  • 133
  • I recently have an where as my service still runs but does no process... I'm starting to think it may be due to "swallowed" exceptions. Wondering if you have any thoughts on my issue? http://stackoverflow.com/questions/41618324/windows-service-runs-but-stops-processing-after-two-days – Tez Wingfield Jan 13 '17 at 09:28
6

When I was working on my own Windows Service, it was stoping itself oddly enough. I thought it was because of unhanded exception. At the moment I am catching unhanded exceptions on text file. First of all you have to create new file ServiceLog.txt on C locations due to logging excaptions on text file. With below coding I got all unhanded exceptions with them line numbers.

using System.Security.Permissions;
using System.IO;

[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)]
    protected override void OnStart(string[] args)
    {   AppDomain currentDomain = AppDomain.CurrentDomain;
        currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
        ...
        Your codes...
        ....
    }
    void MyHandler(object sender, UnhandledExceptionEventArgs args)
    {
        Exception e = (Exception)args.ExceptionObject;
        WriteToFile("Simple Service Error on: {0} " + e.Message + e.StackTrace);
    }
    private void WriteToFile(string text)
    {
        string path = "C:\\ServiceLog.txt";
        using (StreamWriter writer = new StreamWriter(path, true))
        {
            writer.WriteLine(string.Format(text, DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt")));
            writer.Close();
        }
    }
Can DOGRU
  • 69
  • 1
  • 5
4

Know this thread is a bit old, but thought it would be useful to add some comments based on personal experience developing Windows services in .NET. The best approach is to avoid developing under the Service Control Manager as much as you can - for this you need a simple harness that mimics the way services get started - something that can create an instance of your service class (that you already derived from ServiceBase) and call your OnStart, OnStop etc methods. This harness can be a console app or a Windows app as you desire.

This is pretty much the only way I have found of debugging service start-up issues in .NET - the interaction between your code, Visual Studio and the real Service Control Manager just makes the process impossible otherwise.

HTH.

paytools-steve
  • 3,580
  • 3
  • 26
  • 21
  • 3
    +1: Implement all your logic in a separate library and call that from your service. Call the same library from a console application for development/debugging purposes. – Robert Jeppesen Feb 28 '11 at 12:21
  • 2
    I like your approach, but it isn't the only way to debug service startup issues. What I do - especially when debugging services in the production environment - is to setup WinDbg to: 1. attach to the service the moment its host process starts, and 2. open a listening port (needed to overcome the service isolation). Then, it is possible to start debugging using another instance of WinDbg running under your user session. (a configurable call to "RequestAdditionalTime" as the first statement, or a Registry configuration, helps overcoming the time limit the SCM enfores on the service startup time) – M.A. Hanin Sep 02 '13 at 22:06
  • [Topshelf](https://github.com/Topshelf/Topshelf) allows debugging service code as a console application without needing to debug a running service. – fractor Dec 01 '21 at 11:47
2

Just curious, what are you trying to accomplish: avoiding service crashing, or reporting errors?

For reporting, I think your best bet is to add top-level try/catch statements. You can try to log them to the Windows event log and/or a log file.

You can also set the ExitCode property to a non-zero value until you successfully stop the service. If the system administrator starts your service from the Services control panel, and your service stops suddenly with a non-zero exit code, Windows can show an error message with the description of the error.

Paul Williams
  • 16,585
  • 5
  • 47
  • 82
  • Debugging. I've tried catching all of the exceptions, but one is escaping me somehow. I figured this would be a more manageable solution. – Mike Pateras Mar 16 '10 at 18:53
  • Is the exception happening in OnStart or OnStop? Do you have any other information about the exception? – Paul Williams Mar 22 '10 at 13:34