У меня есть приложение, предназначенное для настольных ОС (XP, Vista, Win7), а также для мобильных устройств под управлением Windows XP Embedded. Все платформы работают с полной .Net Framework, , а не Compact Framework. Приложение использует событие AppDomain.UnhandledException
для обнаружения и регистрации любых фатальных ошибок приложения. Ничего необычного там нет, и он отлично работает - по крайней мере, на настольных ОС.
В другом месте приложения есть фрагмент кода, который вызывает метод NetworkInterface.GetAllNetworkInterfaces
для получения списка сетевых карт на компьютере. В Windows XP Embedded - но не в настольных ОС - после вызова этого метода событие AppDomain.UnhandledException
больше не срабатывает при возникновении необработанных исключений. Вместо этого приложение просто вылетает, даже не отображая стандартное диалоговое окно сбоя .Net.
Это известная ошибка, или я что-то не так делаю? Кто-нибудь знает обходной путь для этого?
Вот пример приложения, которое воспроизводит проблему. Этот пример написан на WinForms, но та же проблема возникает и в WPF.
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.");
}
}
}