Rob*_*ner 76 c# exception-handling visual-studio-2010
当我创建一个新项目时,我对未处理的异常会有一个奇怪的行为.这就是我可以重现问题的方法:
1)创建一个新的Windows窗体应用程序(C#,. NET Framework 4,VS2010)
2)将以下代码添加到Form1_Load处理程序:
int vara = 5, varb = 0;
int varc = vara / varb;
int vard = 7;
Run Code Online (Sandbox Code Playgroud)
我希望VS中断并在第二行显示未处理的异常消息.但是,会发生的是第三行只是跳过而没有任何消息,应用程序一直在运行.
我现有的C#项目没有这个问题.所以我想我的新项目是用一些奇怪的默认设置创建的.
有没有人知道我的项目有什么问题?
我试过检查Debug-> Exceptions中的方框.但即使我在try-catch块中处理异常,执行也会中断; 这也不是我想要的.如果我没记错的话,在这个对话框中有一个名为"未处理的异常"的列或者类似的东西,这会让我感到非常兴奋.但在我的项目中只有一列("Thrown").
Han*_*ant 121
这是由wow64仿真层引起的一个令人讨厌的问题,它允许32位代码在64位版本的Windows 7上运行.它吞噬了响应64位窗口管理器生成的通知而运行的代码中的异常,就像Load活动一样.防止调试器看到它并踩到.这个问题很难解决,微软的Windows和DevDiv小组来回指责.DevDiv对此无能为力,Windows认为这是正确且有记录的行为,听起来很神秘.
它肯定是有记录的,但只是没有人理解后果或认为它是合理的行为.特别是当窗口过程从视图中隐藏时,就像在任何使用包装类来隐藏窗口管道的项目中一样.像任何Winforms,WPF或MFC应用程序.基本问题是Microsoft无法弄清楚如何将异常从32位代码流回到64位代码,该代码将通知重新发送回尝试处理或调试异常的32位代码.
附加调试器只是一个问题,你的代码将像往常一样没有炸弹.
项目>属性>构建选项卡>平台目标= AnyCPU并取消选择首选32位.您的应用程序现在将作为64位进程运行,从而消除了wow64故障模式.一些后果,它会在VS2013之前禁用VS版本的Edit + Continue,并且当您对32位代码具有依赖性时可能并不总是可行.
其他可能的解决方法:
Load事件处理程序中编写try/catch,在catch块中编写failfast.Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException)在Main()方法中使用,以便在调试模式下不禁用消息循环中的异常陷阱.然而,这使得所有未处理的异常难以调试,ThreadException事件是无用的.Load事件处理程序.它很少需要它,但它在VB.NET和swan歌曲中非常流行,因为它是默认事件,双击简单地添加了事件处理程序.在应用用户首选项和自动缩放后,当您对实际窗口大小感兴趣时,您才真正需要Load.其他所有内容都属于构造函数.Jon*_*art 10
根据我的经验,当我运行附带的调试器时,我只会看到这个问题.独立运行时,应用程序的行为相同:不会吞下异常.
随着KB976038的推出,您可以按照您的期望再次使用它.我从来没有安装过这个修补程序,所以我假设它是作为Win7 SP1的一部分而来的.
这篇文章中提到了这一点:
这是一些将启用此修补程序的代码:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
在应用程序开头调用它:
[STAThread]
static void Main()
{
Kernel32.DisableUMCallbackFilter();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
Run Code Online (Sandbox Code Playgroud)
我已经确认(使用下面显示的简单示例),这正如您所期望的那样有效.
protected override void OnLoad(EventArgs e) {
throw new Exception("BOOM"); // This will now get caught.
}
Run Code Online (Sandbox Code Playgroud)
所以,我不明白,为什么调试器以前不可能处理交叉内核模式堆栈帧,但是使用这个修补程序,他们以某种方式弄明白了.