NetworkInterface.GetAllNetworkInterfaces 导致 AppDomain.UnhandledException 在 Windows XP Embedded 上停止触发

发布于 2024-08-11 06:54:16 字数 3993 浏览 3 评论 0原文

我有一个针对桌面操作系统(XP、Vista、Win7)以及运行 Windows XP Embedded 的移动设备的应用程序。所有平台都运行完整的.Net Framework,而不是Compact Framework。应用程序使用 AppDomain.UnhandledException 事件来检测并记录任何致命的应用程序错误。没有什么不寻常的,而且它工作得很好——至少在桌面操作系统上是这样。

在应用程序的另一个地方,有一段代码调用 NetworkInterface.GetAllNetworkInterfaces 方法来获取计算机上的 NIC 列表。在 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.");
        }
    }
}

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.");
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文