如何让 WinForms 停止默默地忽略未处理的异常?
Posted
技术标签:
【中文标题】如何让 WinForms 停止默默地忽略未处理的异常?【英文标题】:How can I get WinForms to stop silently ignoring unhandled exceptions? 【发布时间】:2011-11-26 05:51:22 【问题描述】:这变得非常烦人。现在我有一个 winforms 应用程序,但事情不正常,但据我所知,没有抛出异常。在浏览了几乎所有相关代码之后,事实证明在我的应用程序开始时抛出了一个异常。
长话短说,在 WinForms 中,尽管发生异常,但 WinForms 库会忽略它。没有“发生未处理的异常”JIT 消息被抛出,它只是停止处理当前事件并返回到 GUI。
这会导致随机错误,因为加载数据之前发生的异常导致加载数据的代码没有被调用。
为了看到这一点,我创建了一个全新的 WinForms 应用程序,并输入了以下代码:
public partial class Form1 : Form
public Form1()
InitializeComponent();
private void Form1_Load(object sender, EventArgs e)
string blah = null;
blah.Trim();
按 F5 并加载表单而不会显示任何错误,即使抛出空引用也是如此。
然后我尝试转到我的 Program.cs
主要方法并将 Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
添加到它。我的表单仍然加载而不会引发任何错误。
尽管我知道我可以告诉 VS 中断所有异常,但我发现这种情况非常糟糕。它会导致在生产环境中难以调试的非常奇怪的问题,而且由于这是一个内部工具,我真的很想拥有它,所以当异常发生时它实际上会出错,而不是默默地忽略它。
有人知道怎么做吗?
更新: 只是为了更新我从 cmets 学到的东西。
这似乎是 Windows 的 64 位问题,正如我从 this question 了解到的,我在发布之前没有看到。在那个问题中,它指向了一个Microsoft bug report,它有这样的说法:
你好,
此错误已作为“外部”关闭,因为此行为是由 x64 版本的 Windows 处理异常的方式引起的。当用户模式异常跨越内核转换时,x64 版本的 Windows 不允许传播异常。因此,附加的调试器不知道发生了异常,导致调试器无法中断未处理的异常。
不幸的是,Visual Studo 团队无法解决这个问题,这是操作系统设计的结果。有关此问题的所有反馈都应提交给 Windows 团队;但是 Windows 团队认为这是“正确”的操作系统设计,并认为 x86 行为是“不正确的”。
最好的问候, Visual Studio 调试器
话虽如此,如果您的Program.cs
中有以下代码,则不通过 Visual Studio 运行的构建(或使用 Ctrl+F5 运行)似乎会显示 JIT 异常消息框 EXCEPT :
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
该代码将导致窗口忽略异常。
但是,如果您(改为)订阅 Application.ThreadException
事件,不仅您的异常会被捕获,Visual Studio 的调试器会在未处理的异常上中断!
【问题讨论】:
您尝试订阅 Application.UnhandledException 吗? @Tigran: 坏主意,恕我直言...我做了一次 ... 您确定订阅了 Form.Load 事件吗? ...只是一个健全的检查;) VS2010 does not show unhandled exception message in a 64-bit WinForms Application 的可能副本 有趣的链接,虽然一切都符合这个问题,但我的平台已经设置为 x86 并且无法修复它 【参考方案1】:在您的 Program.cs 的 Main 函数中,您还应该确保您已将调用包装起来,以便在 try/catch 中打开表单。另外使用AppDomain.UnhandledException
来捕获异常。我们也添加了Application.ThreadException
。
我相信以下内容会让您了解所有可以抛出的异常...
static void Main()
try
System.Windows.Forms.Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
System.Windows.Forms.Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(OnGuiUnhandedException);
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
var form = new MainForm();
form.ShowDialog();
catch (Exception e)
HandleUnhandledException(e);
finally
// Do stuff
private static void HandleUnhandledException(Object o)
// TODO: Log it!
Exception e = o as Exception;
if (e != null)
private static void OnUnhandledException(Object sender, UnhandledExceptionEventArgs e)
HandleUnhandledException(e.ExceptionObject);
private static void OnGuiUnhandedException(object sender, System.Threading.ThreadExceptionEventArgs e)
HandleUnhandledException(e.Exception);
【讨论】:
注意:可能有更好的方法来拦截所有这些东西,但上面的方法至少可以捕捉到所有东西......这样做是否是好的做法,我将留给其他评论员决定...【参考方案2】:试试下面的。
在您的主应用程序入口点处理异常。 另外,使用ThreadExceptionEventHandler 管理未处理的线程异常这是代码sn-p:
[STAThread]
public static void Main(string[] args)
try
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
//your program entry point
catch (Exception ex)
//manage also these exceptions
private void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
ProcessException(e.Exception);
【讨论】:
订阅ThreadExceptionEventHandler
实际上确实会导致调试器在未处理的异常上中断!现在问题转向在Application_ThreadException
方法中做什么
这不会吞下外部异常吗?这部分有什么建议吗?更多信息:***.com/q/59146505/7453【参考方案3】:
一个简单的解决方法是不在调试器下运行。
调试器出于某种原因屏蔽了异常。如果您正常运行您的应用程序 (Ctrl+F5),您将收到通常的“您的应用程序中发生未处理的异常...继续/退出?”对话框。
【讨论】:
Ctrl+F5 仍然有同样的问题。不抛出异常 使用您的示例代码在我的盒子上扔得很好。您正在运行什么操作系统,它是 32 位还是 64 位?您的项目是 32 位还是 AnyCPU?您正在运行什么版本的 Visual Studio,以及您构建的 .NET 版本是什么? 64 位,平台目标 x86 VS 2010,.Net 4 这里也一样。在 Windows 7 上运行。不知道你在做什么不同,但如果我使用你的示例代码,并且在没有调试的情况下运行,我会立即得到未处理的异常对话框。 仅供参考,如果您的Program.cs
中有 Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
,那么即使 ctrl+f5 也不会显示异常(这就是为什么我第一次建议时没有看到它的原因)跨度>
【参考方案4】:
我经常遇到这种情况并发现有关 64 位操作系统和 Form.Load 事件的问题,我总是强调在 Form.Shown 事件中执行所有启动功能。出于所有实际目的,这是同一件事(除了少数罕见的例外情况),并且 JIT 消息是在 Shown 事件中生成的。
【讨论】:
以上是关于如何让 WinForms 停止默默地忽略未处理的异常?的主要内容,如果未能解决你的问题,请参考以下文章
如何让 Fiddler 停止忽略到 localhost 的流量?
我可以让 Visual Studio 停止任务代码中未处理的异常吗?