代码之家  ›  专栏  ›  技术社区  ›  Anders Sewerin Johansen

如何测试stacktrace walker是否正确跳过库代码

  •  1
  • Anders Sewerin Johansen  · 技术社区  · 6 年前

    我的问题是:我试图跳过一些来自库代码的堆栈帧。如果我想测试这一点,如何最好/最容易地强制stacktrace顶部有一个或多个来自库代码的帧?

    细节:




    在Microsoft.Bing.Platform.ConversationalUnderstanding.ObjectStore.ObjectStoreClientHelperClass.d_u7``2.MoveNext()中
    ---来自引发异常的上一个位置的堆栈结束跟踪---
    在System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()中

    在Microsoft.Bing.Platform.ConversationalUnderstanding.ObjectStore.ObjectStoreCoprocRequest.d_u10`4.MoveNext()中
    ---来自引发异常的上一个位置的堆栈结束跟踪---

    所以基本上我想沿着堆栈框架向下移动,直到找到一个我有实际有用信息的位置,跳过那些没有真正告诉我任何有用信息的库方法。

    下面是我要测试的代码:

    public static (string Path, string Method, int Line) TryGetExceptionOrigin(this Exception e, string defaultPath, string defaultMethod, int defaultLine)
    {
        var defaultRes = (Path: defaultPath, Method: defaultMethod, Line: defaultLine);
        var st = new StackTrace(e.GetInnerMostException(), true);
        if (st.FrameCount == 0)
        {
            return defaultRes;
        }
    
        // Walk down the stack, ignoring framework code etc. with no useful information. We need a file name to be happy
        for (int i = 0; i < st.FrameCount; i++)
        {
            var bottomFrame = st.GetFrame(i);
            if (!(string.IsNullOrEmpty(bottomFrame.GetFileName())))
            {
                return (
                Path: bottomFrame.GetFileName() ?? string.Empty, // Is null if no debug information
                Method: bottomFrame.GetMethod().Name, // Documentation does not say this can ever be null
                Line: bottomFrame.GetFileLineNumber()); // Is 0 if no debug information
            }
        }
    
        // OK no match, we return the default information
        return defaultRes;
    }
    
    2 回复  |  直到 6 年前
        1
  •  0
  •   Cee McSharpface    6 年前

    像这样一些不必要的复杂东西应该很好:

    try
    {
        Func<int> d = () =>
        {
            try
            {
                return Guid.Parse("*").ToByteArray()[0];
            }
            catch (Exception)
            {
                throw;
            }
        };
        Action a = () => { String.Format("{0}", 1 / d()); };
        a();
    }
    catch (Exception ex)
    {
        var useful = ex.TryGetExceptionOrigin(null, null, 0);
    }
    

    此示例生成一个异常调用堆栈,其中包含三个用户代码和四个框架/库代码条目。

        2
  •  0
  •   Anders Sewerin Johansen    6 年前

    https://dotnetthoughts.wordpress.com/2007/10/27/where-did-my-exception-occur/

        private static void ThrowIt()
        {
            Divide(3M, 0M);
        }
    
        static decimal Divide(decimal a, decimal b)
        {
            return (a / b);
        } 
    

    这将生成此stacktrace:

    圣{

    十进制系统运算除法(十进制d1,十进制d2)
    C:\Users\anjohans\source\repos\ExceptionLogging\ExceptionLogging\Program.cs:line C:\Users\anjohans\source\repos\ExceptionLogging\ExceptionLogging\Program.cs:line 88在中的ExceptionLogging.Program.Main(字符串[]args)处 C:\Users\anjohans\source\repos\ExceptionLogging\ExceptionLogging\Program.cs:line