在 C# 中如何收集程序崩溃的堆栈跟踪

Posted

技术标签:

【中文标题】在 C# 中如何收集程序崩溃的堆栈跟踪【英文标题】:In C# how to collect stack trace of program crash 【发布时间】:2012-04-29 11:40:42 【问题描述】:

我是 C# 新手。我正在编写一个基于桌面表单的小型应用程序,我需要在应用程序中具有此功能。

如果应用程序在任何时候崩溃,应用程序应该有最后一次机会来收集堆栈跟踪并将其发回给我...

请给我指示。

我是否需要覆盖我的应用程序的主要入口点的尝试捕获?或者在 C# 应用程序中处理此类事情的最佳方式是什么。

谢谢你,

【问题讨论】:

“电话回家”程序的功能需要精心设计。确保警告用户并考虑最好不要接收哪些数据(密码、姓名,如果它可能包含儿童信息,请格外小心)。也检查一下 - Windows Error Reporting: Getting Started,至少是隐私链接。 【参考方案1】:

要捕获所有未处理的异常,请将其添加到 program.cs:

    [STAThread]
    static void Main()
    
    AppDomain currentDomain = default(AppDomain);
    currentDomain = AppDomain.CurrentDomain;
    // Handler for unhandled exceptions.
    currentDomain.UnhandledException += GlobalUnhandledExceptionHandler;
    // Handler for exceptions in threads behind forms.
    System.Windows.Forms.Application.ThreadException += GlobalThreadExceptionHandler;
    ...
    

private static void GlobalUnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs e)

   Exception ex = default(Exception);
   ex = (Exception)e.ExceptionObject;
   ILog log = LogManager.GetLogger(typeof(Program));
   log.Error(ex.Message + "\n" + ex.StackTrace);


private static void GlobalThreadExceptionHandler(object sender, System.Threading.ThreadExceptionEventArgs e)

   Exception ex = default(Exception);
   ex = e.Exception;
   ILog log = LogManager.GetLogger(typeof(Program)); //Log4NET
   log.Error(ex.Message + "\n" + ex.StackTrace);

您可以通过 exception.StackTrace

获得堆栈跟踪

【讨论】:

感谢您的回答。我正在将您的答案与 Lynn Crumbling 的答案进行比较,我想知道这种方法与他的 .. 相比有什么好处? @user1185422 Aseem 的方法是一种全局解决方案,甚至可以捕获启动时错误、.NET 内部异常、异步操作错误等。Lynn 的方法是一种本地方法,只会捕获内部发生的异常从MainEntryPoint同步调用的方法。我不推荐 Lynn 的方法作为崩溃报告解决方案,因为您可能会错过所有类别的错误。 try-catch 块很好,但是将每一行代码包装在一个 try-catch 中可能会很乏味,而且由于第三方库可能会出现异常,这种方法也解决了这两个问题.您可以继续使用 try-catch 块方法,即便如此,这也是绝对必要的。 @Pavel 和 Aseem——感谢您的解释。我以后会采用这种方法。 感谢您的回答。我尝试在主线程中产生异常或手动设置线程并且它可以工作,但是当我在System.Threading.Tasks.Dataflow 中定义的ActionBlock 方法中产生异常时,程序不会抛出异常,也不会触发currentDomain.UnhandledException 和控制台程序卡住了。【参考方案2】:

如果您将代码包装在 try-catch 中,并且发生异常,您可以在异常处查看堆栈跟踪。是的,你会添加一个 try-catch 来包装你的主入口点。

try

    MainEntryPoint();

catch (Exception exc)

   System.Diagnostics.Debug.Print(exc.Message);  // get at entire error message w/ stacktrace
   System.Diagnostics.Debug.Print(exc.StackTrace);  // or just the stacktrace

【讨论】:

我很想知道订阅 UnhandledException 比使用这种方法有什么好处。 是的,我也在尝试寻找在这个方法上使用该方法的原因。它是否可能捕获应用程序中其他非 UI 线程的异常?我不确定您的解决方案是否也捕获其他线程的异常..【参考方案3】:

如果我是你,我会考虑一个一体化的解决方案,例如免费和开源的 NBug 框架,

http://nbug.codeplex.com/

【讨论】:

使用它提供的示例花了 30 分钟。即使是示例配置应用程序也崩溃了很多。不过这个想法似乎很棒..【参考方案4】:

查看具有Automatic Exception Reporting 功能的 Crypto Obfuscator。

自动异常报告使您可以非常轻松地捕获软件中发生的任何未处理的异常,并且您的用户只需单击一个按钮即可轻松地向您报告这些异常。

异常报告包括所有相关信息,包括完整的堆栈跟踪信息以及所有方法参数和局部变量的值,以及系统信息、异​​常时间、内部版本号和可选的开发人员定义的自定义数据,如日志文件、截图等。

免责声明:我为 Crypto Obfuscator 的开发商 LogicNP Software 工作。

【讨论】:

还有其他类似的商业工具,比如 Red-Gate 的 SmartAssembly,red-gate.com/products/dotnet-development/smartassembly :)

以上是关于在 C# 中如何收集程序崩溃的堆栈跟踪的主要内容,如果未能解决你的问题,请参考以下文章

没有有用的堆栈跟踪的 Android 应用程序崩溃

在应用程序崩溃/C++ 期间获取堆栈跟踪

没有错误或堆栈跟踪的 iOS 崩溃

如何让android打印掉崩溃系统应用程序的核心转储?

在 MonoTouch 应用程序中使用“气泡消息”聊天时,本机堆栈跟踪崩溃

符号化没有崩溃日志的 iOS 崩溃堆栈跟踪