在64位版本的Windows上的WinForms应用程序中,VS2010不显示未处理的exception消息

当我创build一个新的项目,我得到一个奇怪的行为,未处理的exception。 这是我可以重现的问题:

1)创build一个新的Windows窗体应用程序(C#,.NET Framework 4,VS2010)

2)将下面的代码添加到Form1_Load处理程序:

 int vara = 5, varb = 0; int varc = vara / varb; int vard = 7; 

我希望VS打破并在第二行显示一个未处理的exception消息。 但是,会发生什么情况是,第三行只是跳过没有任何消息,应用程序继续运行。

我现有的C#项目没有这个问题。 所以我想我的新项目是用一些奇怪的默认设置创build的。

有没有人有一个想法我的项目有什么问题?

我试图检查Debug-> Exceptions中的框。 但是,即使我在try-catch块中处理exception,执行也会中断; 这也不是我想要的。 如果我没有记错的话,在这个对话框中有一个名为“未处理的exception”的东西或者类似的东西,这会让我兴奋的想要什么。 但在我的项目中只有一列(“投掷”)。

这是一个令人讨厌的问题,由wow64模拟层引起的,它允许32位代码在64位版本的Windows 7上运行。它在响应64位窗口pipe理器生成的通知而运行的代码中吞噬exception,像Load事件一样。 防止debugging器看到并join。这个问题很难解决,微软的Windows和DevDiv组织正在反复指点。 DevDiv不能做任何事情,Windows认为这是正确的和logging的行为,听起来很神秘。

这是肯定的logging,但几乎没有人了解后果或认为这是合理的行为。 特别是当窗口过程隐藏的时候,就像在任何使用包装类隐藏窗口pipe道的工程中一样。 像任何Winforms,WPF或MFC应用程序。 根本问题是微软无法弄清楚如何将32位代码中的exceptionstream回64位代码,这些代码会触发通知返回到试图处理或debuggingexception的32位代码。

这只是一个附加的debugging器的问题,你的代码将像往常一样没有一个炸弹。

项目“>”属性“>”生成“选项卡>”平台目标= AnyCPU并取消select32位“。 您的应用程序现在将作为64位进程运行,消除了wow64失败模式。 一些后果,它禁用编辑+继续的VS2013之前的VS版本,并可能不总是可能的,当你有一个依赖于32位代码。

其他可能的解决方法:

  • debugging>exception>在投掷框中选中CLRexception,强制debugging器在引发exception的代码行停止。
  • Load事件处理程序中写入try / catch,并在catch块中写入failfast。
  • Main()方法中使用Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException) ,以便在debugging模式下不会禁用消息循环中的exception陷阱。 然而,这使所有未处理的exception很难debugging, ThreadException事件是相当无用的。
  • 考虑你的代码是否真的属于Load事件处理程序。 这是非常罕见的需要它,然而在VB.NET和天鹅歌曲是非常stream行,因为它是默认的事件和双击平凡添加事件处理程序。 在应用用户首选项和自动缩放之后,当您对实际的窗口大小感兴趣时,您只需真正需要Load 。 其他一切都属于构造函数。
  • 更新到Windows 8或更高版本,他们已经解决了这个问题。

根据我的经验,当我使用附加的debugging器运行时,我只能看到这个问题。 独立运行时,应用程序的行为相同:exception不被吞下。

随着KB976038的推出,您可以像预期的那样继续工作。 我从来没有安装该修补程序,所以我假设它来作为Win7 SP1的一部分。

这篇文章提到了这个问题:

  • 消失OnLoadexception的情况 – 在x64中的用户模式callbackexception

以下是一些将启用此修补程序的代码:

 public static class Kernel32 { public const uint PROCESS_CALLBACK_FILTER_ENABLED = 0x1; [DllImport("Kernel32.dll")] public static extern bool SetProcessUserModeExceptionPolicy(UInt32 dwFlags); [DllImport("Kernel32.dll")] public static extern bool GetProcessUserModeExceptionPolicy(out UInt32 lpFlags); public static void DisableUMCallbackFilter() { uint flags; GetProcessUserModeExceptionPolicy(out flags); flags &= ~PROCESS_CALLBACK_FILTER_ENABLED; SetProcessUserModeExceptionPolicy(flags); } } 

在您的应用程序开始时调用它:

  [STAThread] static void Main() { Kernel32.DisableUMCallbackFilter(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } 

我已经证实(用下面显示的简单例子),这个工作,就像你所期望的一样。

 protected override void OnLoad(EventArgs e) { throw new Exception("BOOM"); // This will now get caught. } 

所以,我不明白的是,为什么以前debugging器不能处理交叉的内核模式堆栈帧,但是使用这个修补程序,他们以某种方式计算出来了。

正如汉斯所言,编译应用程序并运行exe而不附加debugging器。

对我来说,问题在于改变BindingSource控件绑定到的Class属性名称。 在没有IDE的情况下运行我能够看到错误:

无法绑定到DataSource上的属性或列SendWithoutProofReading 。 参数名称:dataMember

修复BindingSource控件绑定到更新的属性名称解决了问题: 在这里输入图像说明

我正在使用WPF并遇到了同样的问题。 我已经试过汉斯1-3的build议,但不喜欢它们,因为工作室不会停在错误的地方(所以我不能查看我的variables,看看有什么问题)。

所以我试了汉斯的第四个build议。 我惊讶于我的代码有多less可以移动到MainWindow构造函数没有任何问题。 不知道为什么我养成了在Load事件中放置这么多逻辑的习惯,但显然很多都可以在Ctor中完成。

但是,这与1-3有同样的问题。 发生在WPF期间的错误被包装成一个通用的Xamlexception。 (一个内部的例外有真正的错误,但我希望工作室只是在实际的麻烦点击破)。

最后为我工作的是创build一个线程,睡50ms,调度回主线程,并做我需要的…

  void Window_Loaded(object sender, RoutedEventArgs e) { new Thread(() => { Thread.Sleep(50); CrossThread(() => { OnWindowLoaded(); }); }).Start(); } void CrossThread(Action a) { this.Dispatcher.BeginInvoke(a); } void OnWindowLoaded() { ...do my thing... 

这种方式工作室将发生未捕获的exception发生。