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


348

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

public void executeMethod() 
{
    logStackTrace();
    method();
}

Answers:


399

看一下System.Diagnostics名称空间。里面有很多东西!

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

兜一圈学习引擎盖下的情况,这真的很好。

我建议您看看可以实现您的目的的日志记录解决方案(例如NLog,log4net或Microsoft模式和实践企业库)。祝你好运!


74
请记住,StackTrace狗缓慢 -所以要节制利用。
乔纳森·迪金森

213

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

另一个有用的选项是在Visual Studio中使用$CALLER$CALLSTACK 调试变量,因为可以在运行时启用它,而无需重建应用程序。


6
Environment.StackTrace只是new的一个实例StackTrace
丹尼尔(Daniel)

9
@Daniel:是的,但是System.Environment.StackTrace可能是访问该信息的一种更方便的方法。
larsmoa 2012年

6
@AndreiRinea:实际上,我相信您可以使用以下方式访问行号System.Diagnostics.StackTrace:请参阅msdn.microsoft.com/en-us/library/…–
larsmoa

5
Environment.StackTrace总是从头开始是不是很烦人at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo) at System.Environment.get_StackTrace()?在某些人正在寻找时,这不属于当前堆栈跟踪的一部分。
罗里

7
@Rory,看看构造函数StackTrace(int skipFrames,bool fNeedFileInfo),您可以跳过起始帧。在ILSpy中使用该方法,您可以看到它的作用
Walter Vehoeven


16

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

  1. 在要查看堆栈跟踪的位置创建一个断点。
  2. 右键单击断点,然后在VS2015中选择“操作...”。在VS2010中,选择“当被点击时...”,然后启用“打印消息”。
  3. 确保选择“继续执行”。
  4. 输入一些您想打印的文字。
  5. 在任何要查看堆栈跟踪的位置添加$ CALLSTACK。
  6. 在调试器中运行程序。

当然,如果您在另一台计算机上运行代码,这无济于事,但是能够自动吐出堆栈跟踪信息而又不影响发行代码,甚至不需要重新启动程序,都非常方便。


7
如果要查看堆栈跟踪,并且已经在VS调试器中的某个断点处,只需转到Debug-> Windows-> Call Stack。
khargoosh,2015年

5
是的,但是如果您以这种方式进行操作,则无需停止程序即可查看堆栈跟踪。
汉克·舒尔茨

7
Console.WriteLine(
    new System.Diagnostics.StackTrace().ToString()
    );

输出将类似于:

在YourNamespace.Program.executeMethod(String msg)

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

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


-2
   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]);
        }
    }

似乎为我工作


3
这只是产生一个明显的例外。为什么?为什么不简单地显式实例化一个异常,而不是一个本身会引发异常的缺陷呢?达到实际异常所需的附加catch逻辑有什么好处?即使这样,您仍然会忽略关于如何获取堆栈跟踪而没有任何异常的实际发布问题(请阅读标题)。
扁平的

这是一个有效的答案,但真是个可怕的解决方案。任何人都不要使用它... @Jeff无论您在何处执行此操作,都应像其他建议的答案那样使用下降代码代替它。
Tomer W
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.