我正在维护一款使用.NET 4.0框架的遗留C# Winform应用程序。该应用程序工作良好,但偶尔由于应用程序中的错误,在应用程序创建无效数据时应用程序将无法正常工作。
在某些点上,我们将(无效/损坏)数据绑定到datagrid,当它试图将空列映射到datagrid列时,会导致许多错误。
其中包括异常类型为“System.InvalidCastException”的异常在mscorlib.dll中发生,但未在用户代码中处理,以及附加信息:“对象无法从DBNull转换为其他类型。”
以及
异常类型为“System.Reflection.TargetInvocationException”的异常在System.Windows.Forms.dll中发生,但未在用户代码中处理。
这些错误会在Visual Studio调试器下运行时显示一个漂亮的弹出窗口,详细说明错误,并允许我查看错误发生的行。
在这种特殊情况下,我知道问题所在,因此可以轻松地进行更正。然而,这种错误类别在应用程序的其他部分经常发生,因此不总是很明显发生了什么,而且我的用户并不总是提供良好的错误报告。为了解决这个问题,我想向应用程序添加日志记录(使用log4net),在我们的情况下可以这样做,因为每个用户都有自己的应用程序副本,所以我可以在事后获取每个用户的日志。
使用stackoverflow以及其他各种来源的提示,我找到了许多有关设置这些未处理异常处理程序的良好信息。不幸的是,我的处理程序对大多数“未处理”异常都没有被调用。
以下是应用程序的大部分相关部分:
异常处理程序似乎仅在我的代码中直接发生错误时起作用,但当错误直接在.NET库中发生时,处理程序不会被调用,而我希望处理程序对所有未处理异常都会被调用,包括我编写的代码之外的异常。
如果能够在事后在调试器中重现用户的确切步骤,则使用调试器跟踪错误非常有价值。然而,无论是独立运行还是在调试器内部运行,ExceptionLogger 都没有被调用,并且没有任何视觉指示表明发生了任何错误。由于异常被抑制,用户有时直到为时已晚才意识到他们所做的一切完全混乱,数据更加损坏。
应用程序平台正在x86上构建和运行(显然,如果在x64上运行,可能会丢失异常),并且已在64位和32位平台上进行了测试,但行为没有改变。
在某些点上,我们将(无效/损坏)数据绑定到datagrid,当它试图将空列映射到datagrid列时,会导致许多错误。
其中包括异常类型为“System.InvalidCastException”的异常在mscorlib.dll中发生,但未在用户代码中处理,以及附加信息:“对象无法从DBNull转换为其他类型。”
以及
异常类型为“System.Reflection.TargetInvocationException”的异常在System.Windows.Forms.dll中发生,但未在用户代码中处理。
这些错误会在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位平台上进行了测试,但行为没有改变。
ExceptionLogger
没有被调用的原因。搜索代码中的catch
子句,如果终止比继续更好,则删除它们,否则在每个catch
子句中添加日志记录代码。 - groverboy