Thom Little said:
I have a simple C# Winforms application that has an UnhandledException
handler that writes to the log. This works fine if I throw a new exception
(like"bogus") but it does not gain control on a Zero Divide exception.
Is the UnhandledException handler supposed to receive control on all
exceptions or is the UnhandledException hander supposed to receive control
on all exceptions after all other exception handlers have "had a chance" to
service it?
Is the expected behavior that an UnhandledException handler will receive
Zero Divide exceptions or is the expected behavior that an Unhandled
Exception handler will never receive Zero Divide exceptions?
The UnhandledExceptionHandler never gets to see the "Attempted to divide by zero" because the exception IS being handled by the
"Application" class. The dialog box you see is a result of the System.Windows.Forms.NativeWindow.OnThreadException method
executing. A catch block in the Application.Run method is responsible for running it in response to encountering a
System.Exception-derived exception (this behaviour is disabled when the debugger is attached).
To override this behaviour, see a
http://msdn.microsoft.com/library/d...readingthreadexceptioneventargsclasstopic.asp
and code below.
Other problems related to that Exception Dialog can relate to the
<system.windows.forms jitDebugging="true" />
setting in the machine.config or app.config
http://msdn.microsoft.com/library/d...blingjust-in-timedebuggingforwindowsforms.asp
and to the setup of the HKEY_LOCAL_MACHINE\Software\Microsoft\.NETFramework\DbgJITDebugLaunchSetting Registry key
http://msdn.microsoft.com/library/d...ide/html/cpconenablingjit-attachdebugging.asp
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Diagnostics;
using System.Threading;
namespace Unhandled {
public class UnhandledExceptionTest : System.Windows.Forms.Form {
private System.Windows.Forms.Button btnThrow;
private System.ComponentModel.Container components = null;
public UnhandledExceptionTest() {
InitializeComponent();
}
protected override void Dispose( bool disposing ) {
if( disposing ) {
if (components != null) {
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btnThrow = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// btnThrow
//
this.btnThrow.Location = new System.Drawing.Point(104, 24);
this.btnThrow.Name = "btnThrow";
this.btnThrow.TabIndex = 0;
this.btnThrow.Text = "&Throw";
this.btnThrow.Click += new System.EventHandler(this.btnThrow_Click);
//
// UnhandledExceptionTest
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 15);
this.ClientSize = new System.Drawing.Size(320, 65);
this.Controls.Add(this.btnThrow);
this.Name = "UnhandledExceptionTest";
this.Text = "UnhandledExceptionTest";
this.ResumeLayout(false);
}
#endregion
[STAThread]
static void Main() {
// Create AppDomain object
AppDomain adCurrent = AppDomain.CurrentDomain;
// Attach the UnhandledExceptionEventHandler to
// the UnhandledException of the APPDOMAIN object
adCurrent.UnhandledException += new UnhandledExceptionEventHandler(
UnhandledExceptionTest.UnhandledExceptionHandler
);
// Create an instance of the class with the methods
// that will handle the exception.
CustomExceptionHandler eh = new CustomExceptionHandler();
// Add the event handler to the APPLICATION object event.
// This will replace the default Exception dialog box
// shown by NativeWindow.OnThreadException
Application.ThreadException += new ThreadExceptionEventHandler(eh.OnThreadException);
Application.Run(new UnhandledExceptionTest());
}
// This will only catch unhandled exceptions NOT handled
// by System.Windows.Forms.NativeWindow.OnThreadException method.
private static void UnhandledExceptionHandler(
object sender,
UnhandledExceptionEventArgs ue
){
CustomExceptionHandler.Log.WriteEntry(
((Exception)ue.ExceptionObject).Message,
EventLogEntryType.Error
);
Application.Exit(); // Think twice before you just keep going
}
private void btnThrow_Click(object sender, System.EventArgs e) {
int a = 1;
int b = 10/(--a);
}
} // End class UnhandledExceptionTest
// Based on MSDN ThreadExceptionEventArgs Class code example
// Creates a class to handle the exception event.
internal class CustomExceptionHandler {
// Handles the exception event
public void OnThreadException(object sender, ThreadExceptionEventArgs t) {
//
// Do whatever needs to be done here
//
string errorMsg =
"An error occurred please contact the adminstrator "
+ "with the following information:\n\n"
+ t.Exception.Message
+ "\n\nStack Trace:\n"
+ t.Exception.StackTrace;
Log.WriteEntry( errorMsg, EventLogEntryType.Error );
Application.Exit(); // Think twice before you just keep going
}
private static EventLog eventLog_ = null;
private const string logName = "Application";
private const string sourceName = "UnhandledExceptionTest";
private const string machineName = ".";
public static EventLog Log {
get {
if (null != eventLog_) return eventLog_;
if( ! EventLog.SourceExists(sourceName, machineName) )
EventLog.CreateEventSource( sourceName, logName, machineName );
eventLog_ = new EventLog( logName, machineName, sourceName );
return eventLog_;
}
}
} // end class CustomExceptionHandler
} // end namespace Unhandled