浅谈C# StackTrace 类的实例及异常使用


输出文件名、行号、函数名、列号

StackTrace st = new StackTrace(new StackFrame(true));
StackFrame sf = st.GetFrame(0);
//文件名
Console.WriteLine(" File: {0}", sf.GetFileName());     
//函数名                                           
Console.WriteLine(" Method: {0}", sf.GetMethod().Name);     
//文件行号                            
Console.WriteLine(" Line Number: {0}", sf.GetFileLineNumber());                  
Console.WriteLine(" Column Number: {0}", sf.GetFileColumnNumber());

StackTrace 类的实例说明

其中调用GetFrame得到栈空间,参数index 表示栈空间的级别,0表示当前栈空间,1表示上一级的栈空间,依次类推。

在方法中执行以下代码

System.Diagnostics.Debug.WriteLine(new string('*', 78));
System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace();
System.Diagnostics.StackFrame[] sfs = st.GetFrames();
for (int u = 0; u < sfs.Length; ++u)
{
    System.Reflection.MethodBase mb = sfs[u].GetMethod();
    System.Diagnostics.Debug.WriteLine("[CALL STACK][{0}]: {1}.{2}", u, mb.DeclaringType.FullName, mb.Name);
}

在output窗口(Alt+2)看到类似

******************************************************************************
[CALL STACK][0]: WindowsFormsApplication1.Form1.button1_Click
[CALL STACK][1]: System.Windows.Forms.Button.OnMouseUp
[CALL STACK][2]: System.Windows.Forms.Control.WmMouseUp
[CALL STACK][3]: System.Windows.Forms.Control.WndProc
[CALL STACK][4]: System.Windows.Forms.ButtonBase.WndProc
[CALL STACK][5]: System.Windows.Forms.Button.WndProc
[CALL STACK][6]: System.Windows.Forms.NativeWindow.DebuggableCallback
[CALL STACK][7]: System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW
[CALL STACK][8]: System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW
[CALL STACK][9]: System.Windows.Forms.Application+ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop
[CALL STACK][10]: System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner
[CALL STACK][11]: System.Windows.Forms.Application+ThreadContext.RunMessageLoop
[CALL STACK][12]: WindowsFormsApplication1.Program.Main
[CALL STACK][13]: System.AppDomain._nExecuteAssembly
[CALL STACK][14]: Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly
[CALL STACK][15]: System.Threading.ExecutionContext.RunInternal
[CALL STACK][16]: System.Threading.ExecutionContext.Run
[CALL STACK][17]: System.Threading.ExecutionContext.Run
[CALL STACK][18]: System.Threading.ThreadHelper.ThreadStart

再高(dan)级(teng)一点 ,写个公用的静态方法,并用上“DEBUG”条件之,然后……在需要的地方调用之

[System.Diagnostics.Conditional("DEBUG")]
static public void OutputCallStack()
{
    System.Diagnostics.Debug.WriteLine(new string('*', 78));
    System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace();
    System.Diagnostics.StackFrame[] sfs = st.GetFrames();
    for (int u = 1; u < sfs.Length; ++u)
    {
        System.Reflection.MethodBase mb = sfs[u].GetMethod();
        System.Diagnostics.Debug.WriteLine("[CALL STACK][{0}]: {1}.{2}", u, mb.DeclaringType.FullName, mb.Name);
    }
}

C# 捕获异常详情

代码使用try catch将除零错误捕获,捕获后又抛出了此异常!又被外层函数捕捉后,错误中就只留下了throw时的错误行信息。

获取具体的异常

//解决方法
private void button3_Click(object sender, EventArgs e)
{
    try
    {
        test2();
    }
    catch (Exception ex)
    {
        this.textBox1.Text = ex.ToString();
    }
}

private void test2()
{
    try
    {
        test();
    }
    catch (Exception ex)
    {
        //自定义异常
        throw new Exception("出错啦!", ex);
    }
}

throw new Exception("出错啦!", ex); 重新创建了新的自定义异常,并且将原始异常设置为innerException;所以异常信息中包含了多个层次的异常信息。

catch 了异常后,如果不处理,直接写 throw 即可

try
{
    test();
}
catch
{
    //异常处理
    throw;
}

而对于无须异常处理的情况,写法如下:

try
{
    test();
}
finally
{
    //释放资源
}

异常在DEBUG RELEASE版的差异

DEBUG RELEASE在VS调试状态下获取结果相同。

当在RELEASE独立运行时

RELEASE模式下 无ExceptionTest.pdb

System.Exception: 出错啦!
---> System.DivideByZeroException: 试图除以零。
   在 ExceptionTest.Form1.test2() 
  --- 内部异常堆栈跟踪的结尾 ---
   在 ExceptionTest.Form1.test2()
   在 ExceptionTest.Form1.button3_Click(Object sender, EventArgs e)

RELEASE模式下

System.Exception: 出错啦!
---> System.DivideByZeroException: 试图除以零。
   在 ExceptionTest.Form1.test2() 位置 C:\Documents and Settings\Administrator\桌面\ErrorLog\ExceptionTest\Form1.cs:行号 84
   --- 内部异常堆栈跟踪的结尾 ---
   在 ExceptionTest.Form1.test2() 位置 C:\Documents and Settings\Administrator\桌面\ErrorLog\ExceptionTest\Form1.cs:行号 89
   在 ExceptionTest.Form1.button3_Click(Object sender, EventArgs e) 位置 C:\Documents and Settings\Administrator\桌面\ErrorLog\ExceptionTest\Form1.cs:行号 72 

总结

  • 注意在捕获并抛出异常时应使用 throw new Exception("出错啦!", ex); 方式,则可获得异常的具体位置。
  • 当在VS调试或者DEBUG模式下运行程序成都可获得异常发生的具体位置。
  • 但当在独立运行的RELEASE模式下时,异常只会记录最初的调用位置。
  • 当执行目录不包含 *.pdb 文件时,异常信息中不会包含代码及行号信息。

知识共享许可协议
《浅谈C# StackTrace 类的实例及异常使用》 常伟华 创作。
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议 | 3.0 中国大陆许可协议进行许可。

站内公告

A PHP Error was encountered

Severity: Core Warning

Message: PHP Startup: zip: Unable to initialize module Module compiled with module API=20060613 PHP compiled with module API=20090626 These options need to match

Filename: Unknown

Line Number: 0

Backtrace: