An exception does not propagate correctly to the calling function in a Windows Forms application project in Visual Studio .NET (836674)



The information in this article applies to:

  • Microsoft Visual Studio .NET (2003), Enterprise Architect Edition
  • Microsoft Visual Studio .NET (2003), Enterprise Developer Edition
  • Microsoft Visual Studio .NET (2003), Academic Edition
  • Microsoft Visual Studio .NET (2002), Professional Edition
  • Microsoft Visual Studio .NET (2002), Enterprise Architect Edition
  • Microsoft Visual Studio .NET (2002), Enterprise Developer Edition
  • Microsoft Visual Studio .NET (2002), Academic Edition

SYMPTOMS

When you use structured exception handling in a Microsoft Windows Forms application, the exception may not propagate correctly to the calling function. This behavior may occur if you run your Windows Forms application without using the debugger. When this behavior occurs, you may receive the following error message:
An unhandled exception has occurred in your application. If you click continue, the application will ignore this error and attempt to continue. If you click Quit the application will shut down immediately.
My Exception
However, if you run your Windows Forms application with the debugger, you may not receive this error message.

CAUSE

When you run your Windows Forms application without using the debugger, you use the NativeWindow.CallBack method to catch the exception and to prevent the program from unexpectedly quitting (crashing). In the NativeWindow.CallBack method, you populate the exception message by using a standard exception dialog box.

However, if you run your Windows Forms application with the debugger, you do not catch the exception because you use the NativeWindow.DebuggableCallBack method. When you use the NativeWindow.DebuggableCallBack method, the just-in-time (JIT) debugger stops the application from running.

WORKAROUND

To work around this behavior, follow these steps:
  1. In Microsoft Visual Studio .NET, open the Windows Forms project.
  2. Click Solution Explorer.
  3. In Solution Explorer, right-click the project, point to Add, and then click Add New Item. The New Item dialog box appears.
  4. Do one of the following, depending on the version of Visual Studio .NET that you have:
    • In Visual Studio .NET 2003, click Application Configuration File under Template, and then click Open.
    • In Visual Studio .NET 2002, click XML File under Template, type App.config in the Name box, and then click Open.
    The App.config file opens in the Visual Studio .NET IDE.
  5. In the App.config file, replace the existing code with the following code.
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
    <system.windows.forms jitDebugging="true" />
    </configuration>
  6. On the Build menu, click Build Solution.
  7. Press CTRL+F5 to run the application without using the debugger.
Another workaround for this behavior is to use the Application.OnThreadException handler. Add the following code to the Form1 class. This code works the same way both with debugger and without the debugger.
[STAThread] 
static void Main()
{
 CustomExceptionHandler eh = new CustomExceptionHandler(); 
 Application.ThreadException += new ThreadExceptionEventHandler(eh.OnThreadException); 
 Application.Run(new Form1()); 
}
internal class CustomExceptionHandler 
{ 
 public void OnThreadException(object sender, ThreadExceptionEventArgs t) 
 { 
  // MessageBox.Show("OnThreadException - Handling the following exception: \n \n" + t.Exception.Message);
  throw t.Exception; 
 }
} 

STATUS

This behavior is by design.

Note This behavior does not occur in Microsoft Visual Studio 2005.

MORE INFORMATION

Steps to reproduce the behavior

  1. Start Visual Studio .NET.
  2. On the File menu, point to New, and then click Project. The New Project dialog box appears.
  3. Under Project Types, click Visual C# Projects. Under Templates, click Windows Application projects. Click OK. By default, a form that is named Form1 is created.
  4. Switch to the code view.
  5. In the Form1 form, replace the existing code with the following code.
    using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Data;
    
    namespace WindowsApplication1
    {
    	/// <summary>
    	/// Summary description for Form1.
    	/// </summary>
    	public class Form1 : System.Windows.Forms.Form
    	{
    		private System.Windows.Forms.Button button1;
    		/// <summary>
    		/// Windows Form Designer requires this variable.
    		/// </summary>
    		private System.ComponentModel.Container components = null;
    
    		public Form1()
    		{
    			//
    			// Windows Form Designer requires this method.
    			//
    			InitializeComponent();
    
    			//
    			// TODO: Add any constructor code after InitializeComponent call.
    			//
    		}
    
    		/// <summary>
    		/// Clean up any resources that are being used.
    		/// </summary>
    		protected override void Dispose( bool disposing )
    		{
    			if( disposing )
    			{
    				if (components != null) 
    				{
    					components.Dispose();
    				}
    			}
    			base.Dispose( disposing );
    		}
    
    		#region Windows Form Designer generated code
    		/// <summary>
    		/// Windows Form Designer requires this method. Do not modify
    		/// the contents of this method by using the code editor.
    		/// </summary>
    		private void InitializeComponent()
    		{
    			this.button1 = new System.Windows.Forms.Button();
    			this.SuspendLayout();
    			// 
    			// button1
    			// 
    			this.button1.Location = new System.Drawing.Point(64, 104);
    			this.button1.Name = "button1";
    			this.button1.Size = new System.Drawing.Size(160, 40);
    			this.button1.TabIndex = 0;
    			this.button1.Text = "button1";
    			this.button1.Click += new System.EventHandler(this.button1_Click);
    			// 
    			// Form1
    			// 
    			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
    			this.ClientSize = new System.Drawing.Size(292, 266);
    			this.Controls.Add(this.button1);
    			this.Name = "Form1";
    			this.Text = "Form1";
    			this.ResumeLayout(false);
    
    		}
    		#endregion
    
    		/// <summary>
    		/// The main entry point for the application.
    		/// </summary>
    		[STAThread]
    		static void Main() 
    		{
    			try
    			{
    				Application.Run(new Form1());
    			}
    			catch(Exception ex)
    			{
    				MessageBox.Show(ex.Message);
    			}
    			}
    
    
    		private void button1_Click(object sender, System.EventArgs e)
    		{
    			try
    			{
    				Form2 frm = new Form2();
    				frm.Show();
    			}
    			catch (System.Exception exc)
    				  {
    				MessageBox.Show("Handling the following exception: \n \n" +   exc.Message);
    				  }
    		}
    	}
    }
    
  6. In Solution Explorer, right-click the project, point to Add, and then click Add New Item. The Add New Item dialog box appears.
  7. Under Templates, click Windows Form. By default, a form that is named Form2 is created.
  8. In the Form2 form, replace the existing code with the following code.
    using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.Windows.Forms;
    
    namespace WindowsApplication1
    {
    	/// <summary>
    	/// Summary description for Form2.
    	/// </summary>
    	public class Form2 : System.Windows.Forms.Form
    	{
    		/// <summary>
    		/// Windows Form Designer requires this variable.
    		/// </summary>
    		private System.ComponentModel.Container components = null;
    
    		public Form2()
    		{
    			//
    			// Windows Form Designer requires this method.
    			//
    			InitializeComponent();
    
    			//
    			// TODO: Add any constructor code after InitializeComponent call.
    			//
    		}
    
    		/// <summary>
    		/// Clean up any resources that are being used.
    		/// </summary>
    		protected override void Dispose( bool disposing )
    		{
    			if( disposing )
    			{
    				if(components != null)
    				{
    					components.Dispose();
    				}
    			}
    			base.Dispose( disposing );
    		}
    
    		#region Windows Form Designer generated code
    		/// <summary>
    		/// Windows Form Designer requires this method. Do not modify
    		/// the contents of this method by using the code editor.
    		/// </summary>
    		private void InitializeComponent()
    		{
    			// 
    			// Form2
    			// 
    			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
    			this.ClientSize = new System.Drawing.Size(292, 266);
    			this.Name = "Form2";
    			this.Text = "Form2";
    			this.Load += new System.EventHandler(this.Form2_Load);
    
    		}
    		#endregion
    
    		private void Form2_Load(object sender, System.EventArgs e)
    		{
    
    				throw new System.Exception("My Exception");
    
    		}
    	}
    }
  9. On the Build menu, click Build Solution. Then, press CTRL+F5 to run the application without using the debugger.

Modification Type:MajorLast Reviewed:2/24/2006
Keywords:kbvs2005swept kbvs2005doesnotapply kbHotfixServer kbQFE kbvs2002sp1sweep kberrmsg kbpending kbExceptHandling kbProgramming kbDebug kbAppDev kbbug KB836674 kbAudDeveloper