I have an application that targets desktop OSes (XP, Vista, Win7) as well as mobile devices running Windows XP Embedded. All platforms are running the full .Net Framework, not the Compact Framework. The app uses the AppDomain.UnhandledException
event to detect and log any fatal application errors. Nothing unusual there, and it works perfectly -- at least on the desktop OSes.
At another place in the application, there is a piece of code that calls the NetworkInterface.GetAllNetworkInterfaces
method to get a list of NICs on the machine. On Windows XP Embedded -- but not the desktop OSes -- once this method has been called, the AppDomain.UnhandledException
event no longer fires when unhandled exceptions occur. Instead, the app just crashes, without even displaying the standard .Net crash dialog.
Is this a known bug, or am I doing something wrong? Does anybody know a workaround for this?
Here is a sample application that reproduces the problem. This example is written in WinForms, but the same problem occurs in WPF as well.
using System;
using System.Net.NetworkInformation;
using System.Threading;
using System.Windows.Forms;
namespace BugDemo
{
public class BugDemoForm : Form
{
/// <summary>
/// This is the entry point of the application.
/// </summary>
[STAThread]
static void Main()
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
Application.Run(new BugDemoForm());
}
/// <summary>
/// Sets up a simple form with two buttons for reproducing the bug.
/// </summary>
public BugDemoForm()
{
Padding = new Padding(15);
Width = 400;
int halfHeight = (ClientRectangle.Height / 2) - Padding.Vertical;
Button exceptionButton = new Button();
exceptionButton.Dock = DockStyle.Top;
exceptionButton.Height = halfHeight;
exceptionButton.Text = "Test the AppDomain.UnhandledException method";
exceptionButton.Click += exceptionButton_Click;
Controls.Add(exceptionButton);
Button networkInterfacesButton = new Button();
networkInterfacesButton.Dock = DockStyle.Bottom;
networkInterfacesButton.Height = halfHeight;
networkInterfacesButton.Text = "Call the NetworkInterface.GetAllNetworkInterfaces method";
networkInterfacesButton.Click += networkInterfacesButton_Click;
Controls.Add(networkInterfacesButton);
}
/// <summary>
/// Throws an exception on a background thread.
/// This will cause the <see cref="AppDomain.UnhandledException"/> event to fire.
/// </summary>
private static void exceptionButton_Click(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(
delegate(object state)
{
throw new ApplicationException();
});
}
/// <summary>
/// Calls the <see cref="NetworkInterface.GetAllNetworkInterfaces"/> method.
/// Once this method is called, the <see cref="AppDomain.UnhandledException"/> event
/// will no longer fire.
/// </summary>
private static void networkInterfacesButton_Click(object sender, EventArgs e)
{
NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
MessageBox.Show("There are " + nics.Length + " network interfaces on this machine.\n\n"
+ "Now that the NetworkInterface.GetAllNetworkInterfaces method has been called, "
+ "the AppDomain.UnhandledException event will no longer fire when running on "
+ "Windows XP Embedded.");
}
/// <summary>
/// Fires whenever an unhandled exception occurs on a background thread.
/// However, once the <see cref="NetworkInterface.GetAllNetworkInterfaces"/> method has been
/// called, this event no longer fires.
/// </summary>
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
MessageBox.Show("The AppDomain.UnhandledException event fired successfully.\n"
+ "The app will now crash, as expected.");
}
}
}