/* * UnhandledExceptionDlg Class v. 1.1 * * Copyright (c)2006 Vitaly Zayko * * History: * September 26, 2006 - Added "ThreadException" handler, "SetUnhandledExceptionMode", OnShowErrorReport event * and updated the Demo and code comments; * August 29, 2006 - Updated information about Microsoft Windows Error Reporting service and its link; * July 18, 2006 - Initial release. * */ /* More info on MSDN: * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/exceptdotnet.asp * http://msdn2.microsoft.com/en-us/library/system.windows.forms.application.threadexception.aspx * http://msdn2.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx * http://msdn2.microsoft.com/en-us/library/system.windows.forms.unhandledexceptionmode.aspx */ using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms; using System.Threading; using Inssider.Properties; namespace Inssider { internal class SendExceptionClickEventArgs: System.EventArgs { public String UserDescription; public bool SendExceptionDetails; public Exception UnhandledException; public bool RestartApp; public SendExceptionClickEventArgs(bool SendDetailsArg, String Description, Exception ExceptionArg, bool RestartAppArg) { this.SendExceptionDetails = SendDetailsArg; // TRUE if user clicked on "Send Error Report" button and FALSE if on "Don't Send" this.UserDescription = Description; this.UnhandledException = ExceptionArg; // Used to store captured exception this.RestartApp = RestartAppArg; // Contains user's request: should the App to be restarted or not } } /// /// Class for catching unhandled exception with UI dialog. /// class UnhandledExceptionDlg { private bool _dorestart = false; /// /// Set to true if you want to restart your App after falure /// public bool RestartApp { get { return _dorestart; } set { _dorestart = value; } } public delegate void SendExceptionClickHandler(object sender, SendExceptionClickEventArgs args); //public delegate void ShowErrorReportHandler(object sender, System.EventArgs args); /// /// Occurs when user clicks on "Send Error report" button /// public event SendExceptionClickHandler OnSendExceptionClick; /// /// Occurs when user clicks on "click here" link lable to get data that will be send /// public event SendExceptionClickHandler OnShowErrorReportClick; public event SendExceptionClickHandler OnCopyToClipboardClick; /// /// Default constructor /// public UnhandledExceptionDlg() { InitializeApplicationHandlers(); } public void InitializeApplicationHandlers() { // Add the event handler for handling UI thread exceptions to the event: Application.ThreadException += new ThreadExceptionEventHandler(ThreadExceptionFunction); // Set the unhandled exception mode to force all Windows Forms errors to go through our handler: Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); // Add the event handler for handling non-UI thread exceptions to the event: AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledExceptionFunction); } // End /// /// Handle the UI exceptions by showing a dialog box /// /// /// private void ThreadExceptionFunction(Object sender, ThreadExceptionEventArgs e) { // Suppress the Dialog in Debug mode: #if !DEBUG ShowUnhandledExceptionDlg(e.Exception); #endif } /// /// Handle the UI exceptions by showing a dialog box /// /// Sender Object /// Passing arguments: original exception etc. private void UnhandledExceptionFunction(Object sender, UnhandledExceptionEventArgs args) { // Suppress the Dialog in Debug mode: #if !DEBUG ShowUnhandledExceptionDlg((Exception)args.ExceptionObject); #endif } /// /// Raise Exception Dialog box for both UI and non-UI Unhandled Exceptions /// /// Catched exception public void ShowUnhandledExceptionDlg(Exception e) { Exception unhandledException = e; if(unhandledException == null) unhandledException = new Exception("Unknown unhandled Exception was occurred!"); UnhandledExDlgForm exDlgForm = new UnhandledExDlgForm(); try { string appName = System.Diagnostics.Process.GetCurrentProcess().ProcessName; exDlgForm.Text = appName; exDlgForm.labelTitle.Text = String.Format(exDlgForm.labelTitle.Text, appName); // Do not show link label if OnShowErrorReport is not handled exDlgForm.labelLinkTitle.Visible = (OnShowErrorReportClick != null); exDlgForm.linkLabelData.Visible = (OnShowErrorReportClick != null); // Disable the Button if OnSendExceptionClick event is not handled exDlgForm.buttonSend.Enabled = (OnSendExceptionClick != null); // Handle clicks on report link label exDlgForm.linkLabelData.LinkClicked += delegate(object o, LinkLabelLinkClickedEventArgs ev) { if(OnShowErrorReportClick != null) { SendExceptionClickEventArgs ar = new SendExceptionClickEventArgs(true, "", unhandledException, _dorestart); OnShowErrorReportClick(this, ar); } }; exDlgForm.buttonCopy.Click += delegate(object o, EventArgs ev) { if (OnCopyToClipboardClick != null) { SendExceptionClickEventArgs ar = new SendExceptionClickEventArgs(true, exDlgForm.UserDescription, unhandledException, _dorestart); OnCopyToClipboardClick(this, ar); } exDlgForm.buttonCopy.Enabled = false; }; // Show the Dialog box: bool sendDetails = (exDlgForm.ShowDialog() == System.Windows.Forms.DialogResult.Yes); if(OnSendExceptionClick != null) { SendExceptionClickEventArgs ar = new SendExceptionClickEventArgs(sendDetails, exDlgForm.UserDescription, unhandledException, _dorestart); OnSendExceptionClick(this, ar); } } finally { exDlgForm.Dispose(); } } } }