Exception handling in services in a production environment
I have written about using Enterprise Library to log exceptions in a production environment, specifically how to cope when the loggers will not write to files or event logs.
Recently I came across a problem where the whole logging framework was failing to initialise in a production environment. What we got was the usual generic error message and nothing useful in the event logs and obviously the logging framework did not receive anything.
In this instance the problem was that the config file (which was being rewritten between deployment environments) was malformed. However in principle the logging framework could fail to start for any number of reasons.
Since this has happen as a matter of routine I always wrap the logging framework initialisation in a try catch the will write any errors to the debug console so that I can use DbgView to see what has gone wrong.
static private void OutputToDebugConsole(string format, params object[] args) { Trace.Write(string.Format(format, args)); } protected override void OnStart(string[] args) { OutputToDebugConsole("RemoteControlService Starting"); try { _iocContainer = InitializeIocContainer(); _logwriter = _iocContainer.Resolve(); } catch (Exception ex) { // we have no other method of communication - lets try the debug console OutputToDebugConsole("RemoteControlService Error creating logger: {0}", ex.Message); throw; }
Writing to the debug console is a good choice because DbgView does not require any installation, just copy the EXE and run it. This means that operations are more likely to allow it to be run in a production environment. To be able to see the errors that are produced when trying to start the service you must run DbgView as administrator and also enable “Capture Global Win32” on the Capture menu of DbgView.
For example this is what we see if an arbitrary error was thrown by trying to initialise the _logwriter.
Its also worth noting that Trace.Write is used rather than Debug.Write as calls to Trace will still produce output when we compile for release whereas Debug will not.