7

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

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

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

有没有更好的方法来做到这一点?只需包含核心 ASP.NET 之外的所有内容。

4

3 回答 3

9

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

如果您只需要一个简单的过滤器,您可以执行以下操作之一:

  • 去掉以“System”开头的类中的所有方法。或“微软”。(因为所有 .NET 库都放在那里)。
  • 找到方法所在的程序集(见前文),然后检查AssemblyCompanyAttribute并过滤“Microsoft Corporation”制造的程序集)。这比以前的方法要好,因为有时我会看到将自己的类型放入System命名空间的库。

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

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

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

于 2012-11-19T10:25:52.117 回答
7

如果您部署您的“*.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);
        }
于 2014-01-21T11:57:34.667 回答
0

我遇到了同样的问题,但我使用了 NLog 和 TraceSource 并将 System.Net 跟踪事件重定向到 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,无效的

于 2016-05-17T13:16:19.073 回答