如何在 .NET 中毫无例外地打印当前的堆栈跟踪?

Posted

技术标签:

【中文标题】如何在 .NET 中毫无例外地打印当前的堆栈跟踪?【英文标题】:How to print the current Stack Trace in .NET without any exception? 【发布时间】:2010-10-06 14:40:52 【问题描述】:

我有一个常规的 C# 代码。 我没有例外。我想以编程方式记录当前堆栈跟踪以进行调试。示例:

public void executeMethod() 

    logStackTrace();
    method();

【问题讨论】:

【参考方案1】:

查看System.Diagnostics 命名空间。里面有很多好吃的!

System.Diagnostics.StackTrace t = new System.Diagnostics.StackTrace();

这真是太好了,可以四处看看以了解引擎盖下发生了什么。

我建议您查看日志解决方案(例如 NLog、log4net 或 Microsoft 模式和实践企业库),这些解决方案可能会实现您的目的,然后再实现一些目标。

【讨论】:

请记住,StackTrace狗慢 - 所以要谨慎使用它。【参考方案2】:

System.Diagnostics.StackTrace 的替代方法是使用 System.Environment.StackTrace,它返回堆栈跟踪的字符串表示形式。

另一个有用的选项是使用$CALLER$CALLSTACK debugging variables in Visual Studio,因为这可以在运行时启用而无需重新构建应用程序。

【讨论】:

Environment.StackTrace just new 是 StackTrace 的一个实例。 @Daniel:是的,但System.Environment.StackTrace 可能是访问该信息的更方便的方式。 @AndreiRinea:实际上,我相信您可以使用 System.Diagnostics.StackTrace 访问行号 - 请参阅 msdn.microsoft.com/en-us/library/… Environment.StackTrace 总是以at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo) at System.Environment.get_StackTrace() 开头不是很烦人吗?这不是当前堆栈跟踪的一部分,因为有人正在寻找它。 @Rory,看看构造函数 StackTrace(int skipFrames, bool fNeedFileInfo),可以跳过起始帧。在 ILSpy 中打开该方法,您可以看到它的作用【参考方案3】:

有两种方法可以做到这一点。 System.Diagnostics.StackTrace() 将为您提供当前线程的堆栈跟踪。如果您引用了Thread 实例,则可以通过StackTrace() 的重载版本获取该实例的堆栈跟踪。

您可能还想查看 Stack Overflow 问题How to get non-current thread's stacktrace?

【讨论】:

错误 CS1955 不可调用的成员 'StackTrace' 不能像方法一样使用。【参考方案4】:

您也可以在 Visual Studio 调试器中执行此操作,而无需修改代码。

    在要查看堆栈跟踪的位置创建断点。 右键单击断点,在VS2015中选择“Actions...”。在 VS2010 中,选择“When Hit...”,然后启用“Print a message”。 确保选中“继续执行”。 输入一些您想打印出来的文本。 在要查看堆栈跟踪的任何位置添加 $CALLSTACK。 在调试器中运行程序。

当然,如果您在另一台机器上运行代码,这将无济于事,但能够自动吐出堆栈跟踪而不影响发布代码甚至不需要重新启动程序。

【讨论】:

如果您想查看堆栈跟踪并且您已经在 VS 调试器的断点处,只需转到 Debug->Windows->Call Stack。 是的,但是如果你这样做,程序不必停下来让你看到堆栈跟踪。【参考方案5】:
Console.WriteLine(
    new System.Diagnostics.StackTrace().ToString()
    );

输出将类似于:

在 YourNamespace.Program.executeMethod(String msg)

在 YourNamespace.Program.Main(String[] args)

Console.WriteLine 替换为您的Log 方法。其实有 Console.WriteLine 案例不需要.ToString(),因为它接受 object。但是您的 Log(string msg) 方法可能需要它。

【讨论】:

【参考方案6】:

这对我有用:

Debug.WriteLine(Environment.StackTrace);

【讨论】:

【参考方案7】:
   private void ExceptionTest()
    
        try
        
            int j = 0;
            int i = 5;
            i = 1 / j;
        
        catch (Exception ex)
        
            Console.WriteLine("Error: " + ex.Message);
            var stList = ex.StackTrace.ToString().Split('\\');
            Console.WriteLine("Exception occurred at " + stList[stList.Count() - 1]);
        
    

似乎对我有用

【讨论】:

这只是产生一个明显的异常。为什么?为什么不简单地显式实例化一个异常,而不是一个本身会引发异常的缺陷呢?获取实际异常所需的额外捕获逻辑有什么好处?即便如此,您仍然忽略了关于如何获取堆栈跟踪的实际发布问题没有任何例外(阅读标题)。 这是一个有效的答案,但却是一个糟糕透顶的解决方案。没有人应该使用它...@Jeff 无论您在哪里这样做,都将其替换为其他答案所建议的下降代码。

以上是关于如何在 .NET 中毫无例外地打印当前的堆栈跟踪?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Java 中获取当前堆栈跟踪?

在linux平台上用c/c++打印进程的所有线程堆栈跟踪

从 C# 打印堆栈跟踪信息

如何在 Nest.js 中参考打字稿源打印堆栈跟踪

如何在 JSP 页面中打印错误堆栈跟踪?

如何打印 C++ 中捕获的异常的堆栈跟踪和 C++ 中的代码注入