从StackTrace中过滤掉非用户代码方法

时间:2012-11-19 10:11:06

标签: c# asp.net .net

我正在尝试实现更复杂的错误处理。为了实现我的目标,我需要从curent StackTrace中过滤掉非用户代码方法(框架)。

在ASP.NET典型的StackTrace中,您可能会猜到许多方法与调试目的无关,因为它们不在用户代码中。 Visual Studio为您提供了筛选出这个非用户代码(框架)的选项,因此我猜它是可能的。然而,在探索StackFrames(以及方法,模块,程序集......)的方法和属性大约30分钟后,我找不到任何可用于识别“系统”框架的方法。

我最终手动指定了我想记录的模块(模块是程序集的一部分,在我的情况下是1:1)。

有没有更好的方法呢?简单地包括核心ASP.NET之外的所有内容。

3 个答案:

答案 0 :(得分:6)

如果您部署'* .pdb'文件并且只是尝试从异常中获取堆栈跟踪,则可以获取异常的StackTrace属性并将其拆分为行并过滤掉不具有的行有一个源代码参考。

        catch (Exception ex)
        {
            var lines = ex.StackTrace
                .Split(new[] {Environment.NewLine}, StringSplitOptions.None)
                .Where(l => Regex.IsMatch(l, @"([^\)]*\)) in (.*):line (\d)*$"));
            var userStackTrace = string.Join(Environment.NewLine, lines);
        }

答案 1 :(得分:5)

StackFrame类具有GetMethod()成员函数,来自检索到的MethodBase对象。

如果你需要的只是一个天真的过滤器,你可以做以下其中一个:

  • 删除以“System”开头的类中的每个方法。或“微软”。 (因为所有的.NET库都放在那里)。
  • 找到方法所在的程序集(参见前进),然后检查AssemblyCompanyAttribute并筛选“Microsoft Corporation”制作的程序集。这比以前的方法更好,因为有时候我看到了将自己的类型放在System命名空间中的库。

如果您需要更多内容,可以获取定义该方法的模块(MethodBase.Module)。现在您有两个选择:

  • 如果所有程序集都已签名,则只能显示具有该公钥标记的方法(获取使用Module.Assembly属性定义模块的程序集,使用AssemblyName构建Assembly.FullName对象然后检查AssemblyName.KeyPair属性的公钥,它必须与您的公钥令牌匹配(只需与GetExecutingAssembly()进行比较)。
  • 如果不是所有程序集都已签名,则可以执行相同的操作,但过滤掉与 system 程序集的公钥标记匹配的所有程序集(这可能是最简单的情况,它将包括第三部分图书馆。)

请注意,并非所有系统程序集都具有相同的公钥标记(即使在相同的Framework版本中),因此您必须收集并检查密钥列表(只需浏览c:\windows\assembly即可阅读它们)。一种好的方法是检查公钥,然后使用AssemblyCompanyAttribute应用第二个过滤器。

答案 2 :(得分:0)

我遇到了同样的问题,但我使用了NLog和TraceSource,并将System.Net Trace事件重定向到NLog目标。也就是说,过滤掉系统组件并没有完全削减它,所以我必须检查自定义属性:

    private static bool IsOkay(StackFrame arg)
    {
        var method = arg.GetMethod();
        var methodAttributes = new Attribute[] { }
            .Concat(method.GetCustomAttributes<DebuggerHiddenAttribute>())
            .Concat(method.GetCustomAttributes<CompilerGeneratedAttribute>());

        if (methodAttributes.Any())
            return false;

        var methodDeclearingType = method.DeclaringType;
        var methodDeclearingTypeAttributes = new Attribute[] { }
            .Concat(methodDeclearingType.GetCustomAttributes<CompilerGeneratedAttribute>());

        if (methodDeclearingTypeAttributes.Any())
            return false;

        var methodDeclearingTypeModule = methodDeclearingType.Module;
        var methodDeclearingTypeModuleAttributes = new Attribute[] { }
            .Concat(methodDeclearingTypeModule.GetCustomAttributes<UnverifiableCodeAttribute>());

        if (methodDeclearingTypeModuleAttributes.Any())
            return false;

        return true;
    }

BR, incureforce