我正在使用.NET 4.0框架维护一个传统的C#Winform应用程序。应用程序运行正常,但偶尔由于应用程序中的错误,当应用程序在数据库中创建无效数据时,应用程序将无法正常工作。
在某些点上,我们将(无效/损坏的)数据绑定到数据网格,这会在尝试将空列映射到数据网格列时导致大量错误。
mscorlib.dll中发生了'System.InvalidCastException'类型的异常,但未在用户代码中处理
附加信息:无法将对象从DBNull强制转换为其他类型。
以及
System.Windows.Forms.dll中发生了'System.Reflection.TargetInvocationException'类型的异常,但未在用户代码中处理
错误会导致在Visual Studio调试器下运行时显示一个很好的弹出窗口,详细说明错误,并允许我查看错误发生的行。
在这种特殊情况下,我知道问题是什么,所以我可以很容易地纠正它。但是,这类错误在应用程序的其他部分中经常发生,因此并不总是很明显发生了什么,并且我的用户并不总是提供良好的错误报告。为了尝试解决这个问题,我想在应用程序中添加日志记录(使用log4net),这适用于我们的情况,因为每个用户都拥有自己的应用程序副本,因此我可以在事后获得每用户日志。
使用stackoverflow中的提示以及其他各种来源,我发现了许多关于为这些未处理的异常设置处理程序的好信息。不幸的是,我的处理程序并没有被称为大多数“未处理”的例外。
该应用程序的主要相关部分如下:
static class Program {
private static readonly ILog log = LogManager.GetLogger("Main");
static void Main() {
// Add some error handlers which log error data to the logfile
//
// For UI events (set the unhandled exception mode to force all Windows Forms
// errors to go through our handler)
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
Application.ThreadException += new ThreadExceptionEventHandler(delegate(object s, ThreadExceptionEventArgs e) {
ExceptionLogger(e.Exception);
});
// Non-UI thread exceptions
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(delegate(object sender, UnhandledExceptionEventArgs e) {
ExceptionLogger(e.ExceptionObject as Exception);
});
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
log.Debug("Starting Application");
Application.Run(mainForm = new MainForm());
}
private static void ExceptionLogger(Exception e) {
log.Error("Unhandled Error", e);
string errorMsg = "An application error occurred. Please contact the administrator with the following information:\n\n";
errorMsg = errorMsg + e.Message + "\n\nStack Trace:\n" + e.StackTrace;
if (MessageBox.Show(errorMsg, "TLMS Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Stop) == DialogResult.Abort)
Application.Exit();
}
如果错误直接发生在我自己的代码中,异常处理程序似乎有效,但是如果错误直接出现在.NET库中,则不会调用处理程序,而我希望处理程序调用所有未处理的异常,包括我编写的代码之外的那些。
如果我可以在事后重新创建调试器中的确切用户步骤,那么能够使用调试器来跟踪错误是非常宝贵的。但是,在任何时候都不会调用ExceptionLogger,无论是独立运行还是在调试器内运行,并且没有可视指示表明发生了任何错误。由于异常被抑制,用户有时甚至不会意识到他们所做的一切都完全搞砸了,而且数据更加腐败。
应用程序平台正在构建并在x86上运行(显然,如果在x64上运行,异常可能会丢失),并且该应用程序已在64位和32位平台上进行了测试,但行为没有任何变化。
答案 0 :(得分:0)
当应用程序在调试器中运行时,您只能看到“但未处理”。当它在调试器外运行时,异常被抑制。如果我有这个正确的话,我仍然认为该应用程序处理异常,因为调试器有时会改变应用程序的行为。
我确认InvalidCastException
是.NET 4+在异常上下文是非托管代码时处理不同的一组异常之一。应用程序可以覆盖此特殊处理(请参阅All about Corrupted State Exceptions in .NET 4),但调试器可能会忽略覆盖。这里有很多网络资源,另见MSDN Magazine中的一个。
编辑:如果您的应用用户安装了.NET 3.5或更低版本,那么该应用无需应用上述资源中描述的覆盖。