我想知道最好的方法是“如果所有其他方法都失败了”。
我的意思是,您在应用程序中处理尽可能多的异常, 但仍然有一定的bug,所以我需要有一些东西 捕获所有未处理的异常,以便我可以收集信息和存储 它们在数据库中或提交给Web服务。
AppDomain.CurrentDomain.UnhandledException事件是否捕获了所有内容? 即使应用程序是多线程的?
附注:Windows Vista公开了允许任何应用程序的本机API函数 在崩溃后自我恢复......现在想不到这个名字......但我宁愿不这样做 使用它,因为我们的许多用户仍在使用Windows XP。
答案 0 :(得分:32)
我刚刚玩过AppDomain的UnhandledException行为, (这是未处理的异常在注册的最后阶段)
是的,在处理完事件处理程序后,您的应用程序将被终止并显示令人讨厌的“...程序停止工作对话框”。
:) 你仍然可以避免这种情况。
退房:
class Program
{
void Run()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Console.WriteLine("Press enter to exit.");
do
{
(new Thread(delegate()
{
throw new ArgumentException("ha-ha");
})).Start();
} while (Console.ReadLine().Trim().ToLowerInvariant() == "x");
Console.WriteLine("last good-bye");
}
int r = 0;
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Interlocked.Increment(ref r);
Console.WriteLine("handled. {0}", r);
Console.WriteLine("Terminating " + e.IsTerminating.ToString());
Thread.CurrentThread.IsBackground = true;
Thread.CurrentThread.Name = "Dead thread";
while (true)
Thread.Sleep(TimeSpan.FromHours(1));
//Process.GetCurrentProcess().Kill();
}
static void Main(string[] args)
{
Console.WriteLine("...");
(new Program()).Run();
}
}
P.S。在较高级别处理Application.ThreadException(WinForms)或DispatcherUnhandledException(WPF)的未处理。
答案 1 :(得分:16)
在ASP.NET中,您使用Application_Error
文件中的Global.asax
函数。
在WinForms中,您使用MyApplication_UnhandledException
文件中的ApplicationEvents
如果代码中出现未处理的异常,则会调用这两个函数。您可以记录异常并从这些函数向用户显示一条好消息。
答案 2 :(得分:13)
对于Winform应用程序,除了AppDomain.CurrentDomain.UnhandledException之外,我还使用Application.ThreadException和Application.SetUnhandledExceptionMode(w / UnhandledExceptionMode.CatchException)。这种组合似乎抓住了一切。
答案 3 :(得分:6)
在主线程上,您有以下选项:
AppDomain.CurrentDomain.UnhandledException
Application.ThreadException
Application_Error
对于其他主题:
请记住,这些事件不会处理异常,它们只是向应用程序报告 - 通常在做任何有用的事情为时已晚关于他们
记录异常是好的,但监控应用程序更好; - )
警告:我是SafeThread文章的作者。
答案 4 :(得分:4)
对于WinForms,不要忘记附加到当前Thread的未处理异常事件(特别是如果您使用多线程)。
有关最佳做法here和here以及here (probably the best exception handling article for .net)
的一些链接答案 5 :(得分:2)
还有一个名为ELMAH的很酷的东西,它会记录Web应用程序中发生的任何ASP.NET错误。我知道你在询问Winform App解决方案,但我觉得这对于在网络应用上需要这种类型的任何人都有好处。我们在工作的地方使用它,它在调试方面非常有用(特别是在生产服务器上!)
这里有一些功能(从页面上拉出来):
- 记录几乎所有未处理的例外情况。
- 远程查看已重新编码的例外日志的网页。
- 用于远程查看任何一个已记录异常的完整详细信息的网页。
- 在很多情况下,你可以查看死亡的原始黄色屏幕 为给定的ASP.NET生成的 异常,即使使用customErrors模式 关掉了。
- 发生时每个错误的电子邮件通知。
- 日志中最近15个错误的RSS提要。
- 日志的许多后备存储实现,包括 内存,Microsoft SQL Server和 几个由社区贡献。
答案 6 :(得分:2)
即使在多线程应用程序中,您也可以监视该处理程序中的大多数异常,但.NET(从2.0开始)将不允许您取消未处理的异常,除非您启用1.1兼容模式。当发生这种情况时,AppDomain将被关闭,无论如何。您可以做的最好的事情是在不同的AppDomain中启动应用程序,以便您可以处理此异常并创建一个新的AppDomain来重新启动应用程序。
答案 7 :(得分:0)
我正在使用以下方法,它可以工作并大大减少代码量(但我不确定是否有更好的方法或它的缺陷可能是什么。 每当你打电话: 我认为给予弊端的态度会礼貌地澄清他们的行为; )
try
{
CallTheCodeThatMightThrowException()
}
catch (Exception ex)
{
System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace ();
Utils.ErrorHandler.Trap ( ref objUser, st, ex );
} //eof catch
这是ErrorHandler代码: 只是为了弄清楚 - :objUser - 是为appusers建模的对象(你可能会得到诸如域名,部门,区域等信息用于记录目的 ILog记录器 - 是记录对象 - 例如执行日志记录活动的人 StackTrace st - StackTrace对象为您提供应用程序的调试信息
using System;
using log4net; //or another logging platform
namespace GenApp.Utils
{
public class ErrorHandler
{
public static void Trap ( Bo.User objUser, ILog logger, System.Diagnostics.StackTrace st, Exception ex )
{
if (ex is NullReferenceException)
{
//do stuff for this ex type
} //eof if
if (ex is System.InvalidOperationException)
{
//do stuff for this ex type
} //eof if
if (ex is System.IndexOutOfRangeException)
{
//do stuff for this ex type
} //eof if
if (ex is System.Data.SqlClient.SqlException)
{
//do stuff for this ex type
} //eof if
if (ex is System.FormatException)
{
//do stuff for this ex type
} //eof if
if (ex is Exception)
{
//do stuff for this ex type
} //eof catch
} //eof method
}//eof class
} //eof namesp
答案 8 :(得分:0)
在magedd GUI应用程序中,默认情况下,源自GUI线程的异常由分配给Application.ThreadException的任何内容处理。
源自其他线程的异常由AppDomain.CurrentDomain.UnhandledException处理。
如果您希望GUI线程异常与非GUI GUI一样工作,以便它们由AppDomain.CurrentDomain.UnhandledException处理,您可以这样做:
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
使用ThreadException捕获GUI线程异常的一个好处是,您可以使用让应用程序继续运行的选项。要确保没有配置文件覆盖默认行为,您可以调用:
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
您仍然容易受到行为不端的原生dll的异常攻击。如果本机dll使用Win32 SetUnhandledExceptionFilter安装自己的处理程序,则应该将指针保存到前一个过滤器并调用它。如果不这样做,你的处理程序就不会被调用。