private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { if (!Loggers.IsUsed(this)) { return; } //Can be safely cast to Exception if RuntimeCompatibilityAttribute(WrapNonException=true) has been applied to your assembly, //which is automatically done for you since .net 2.0. 'Non exceptions' will be wrapped in RuntimeWrappedException. var ex = e.ExceptionObject as Exception; var frame = GetApplicableFrame(ex); string sourceFile = frame.GetFileName(); string description = "An unhandled exception occured and killed the application!"; if (sourceFile == null) { description += " SourceFile and Line are not available because the application does not have (up-to-date) .pdb files included in the folder holding the binaries where the exception occured."; } //Do not notify in write exceptions, they will not be handled anyways. LogWriteException = null; //_backgroundWorkQueue is not used because its background thread gets disposed if the application halts. However, we dispose it first so there is absolutely no chance that LogEntryWriteCallback is called by 2 threads at the same time. _backgroundWorkQueue.Dispose(); //Create a readable watson buckets. (_watsonBuckets holds a byte array.) //Watson buckets are somewhat handy for when there is no stacktrace available, or you cannot trace into third-party assemblies. //Only applicable with unhandled exceptions. //I did not simply replace the value for _watsonBuckets in the exception, because the Windows Error Report tool would not work: //You can get the path to the minidump there. The minidump can be analyzed using a tool like WinDbg. //Downside: The output contains a serialized byte array. //http://msdn.microsoft.com/en-us/library/ms404466(v=VS.110).aspx //http://mrpfister.com/programming/demystifying-clr20r3-error-messages/ //http://mrpfister.com/programming/opcodes-msil-and-reflecting-net-code/ ReadableWatsonBucketParameters readableWatsonBucketParameters = null; FieldInfo watsonBucketsField = ex.GetType().GetField("_watsonBuckets", BindingFlags.Instance | BindingFlags.NonPublic); if (watsonBucketsField != null) { byte[] arr = watsonBucketsField.GetValue(ex) as byte[]; if (arr != null) { var str = MarshalBytesToStruct <BucketParameters>(arr); readableWatsonBucketParameters = new ReadableWatsonBucketParameters(str); } } LogEntryWriteCallback(Level.Fatal, description, ex, new object[] { sender }, frame.GetMethod().Name, sourceFile, frame.GetFileLineNumber(), LogToDebug, readableWatsonBucketParameters); }