我正在尝试实现更复杂的错误处理。为了实现我的目标,我需要从curent StackTrace中过滤掉非用户代码方法(框架)。
在ASP.NET典型的StackTrace中,您可能会猜到许多方法与调试目的无关,因为它们不在用户代码中。 Visual Studio为您提供了筛选出这个非用户代码(框架)的选项,因此我猜它是可能的。然而,在探索StackFrames(以及方法,模块,程序集......)的方法和属性大约30分钟后,我找不到任何可用于识别“系统”框架的方法。
我最终手动指定了我想记录的模块(模块是程序集的一部分,在我的情况下是1:1)。
有没有更好的方法呢?简单地包括核心ASP.NET之外的所有内容。
答案 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
对象。
如果你需要的只是一个天真的过滤器,你可以做以下其中一个:
AssemblyCompanyAttribute
并筛选“Microsoft Corporation”制作的程序集。这比以前的方法更好,因为有时候我看到了将自己的类型放在System
命名空间中的库。如果您需要更多内容,可以获取定义该方法的模块(MethodBase.Module
)。现在您有两个选择:
Module.Assembly
属性定义模块的程序集,使用AssemblyName
构建Assembly.FullName
对象然后检查AssemblyName.KeyPair
属性的公钥,它必须与您的公钥令牌匹配(只需与GetExecutingAssembly()
进行比较)。请注意,并非所有系统程序集都具有相同的公钥标记(即使在相同的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