在.netexception中如何获得具有参数值的堆栈跟踪
我正在尝试在.net(c#)中添加一个未处理的exception处理程序,该程序应该尽可能为“用户”提供帮助。 最终用户大多是程序员,所以他们只需要提示他们操作错误的对象。
我正在开发一个窗口类似于Windows XP的错误报告,当一个应用程序崩溃,但给出尽可能多的imediate信息imediatly关于抛出的exception。
虽然堆栈跟踪使我(因为我有源代码)查明问题的根源,用户没有它,所以他们丢失没有进一步的信息。 不用说,我不得不花费大量的时间来支持这个工具。
有几个系统exception,如Dictionary集合引发的KeyNotFoundExceptionexception,因为它们没有在消息中包含没有find的关键字,所以这真是令我烦恼。 我可以使用大量的try catch块来填充代码,但是它相当具有侵略性,并且有更多的代码需要维护,更不用说更多的string了,而这些string必须被本地化。
最后问题:有没有什么办法来获得(在运行时)调用堆栈跟踪中的每个函数的参数的值? 只有这一点可以解决90%的支持电话。
我不认为System.Diagnostics.StackFrame提供参数信息(方法签名除外)。
您可以通过AOP跟踪logging来处理麻烦的调用,甚至可以使用exception拦截function来有条件地logging日志,而不必乱丢代码。 看看http://www.postsharp.org/ 。
同样,我还没有发现任何东西在运行时自动派生参数。 相反,我使用了Visual Studio加载项来生成显式打包参数的代码,如下所示:
public class ExceptionHandler { public static bool HandleException(Exception ex, IList<Param> parameters) { /* * Log the exception * * Return true to rethrow the original exception, * else false */ } } public class Param { public string Name { get; set; } public object Value { get; set; } } public class MyClass { public void RenderSomeText(int lineNumber, string text, RenderingContext context) { try { /* * Do some work */ throw new ApplicationException("Something bad happened"); } catch (Exception ex) { if (ExceptionHandler.HandleException( ex, new List<Param> { new Param { Name = "lineNumber", Value=lineNumber }, new Param { Name = "text", Value=text }, new Param { Name = "context", Value=context} })) { throw; } } } }
编辑:或者,通过使参数HandleException一个参数数组:
public static bool HandleException(Exception ex, params Param[] parameters) { ... } ... if (ExceptionHandler.HandleException( ex, new Param { Name = "lineNumber", Value=lineNumber }, new Param { Name = "text", Value=text }, new Param { Name = "context", Value=context} )) { throw; } ...
生成额外的代码来明确地将parameter passing给exception处理程序是有点痛苦的,但是使用外接程序至less可以自动化它。
自定义属性可用于注释不希望加载项传递给exception处理程序的任何参数:
public UserToken RegisterUser( string userId, [NoLog] string password ) { }
2ND编辑:
请注意,我完全忘了AVICode:
他们使用呼叫拦截技术来提供这种信息,所以它必须是可能的。
不幸的是,除了debugging工具实际连接到应用程序之外,您无法从调用堆栈中获取参数的实际值。 但是,通过在System.Diagnostics中使用StackTrace和StackFrame对象,您可以遍历调用堆栈并读出所有调用的方法以及参数名称和types。 你会这样做:
System.Diagnostics.StackTrace callStack = new System.Diagnostics.StackTrace(); System.Diagnostics.StackFrame frame = null; System.Reflection.MethodBase calledMethod = null; System.Reflection.ParameterInfo [] passedParams = null; for (int x = 0; x < callStack.FrameCount; x++) { frame = callStack.GetFrame(x); calledMethod = frame.GetMethod(); passedParams = calledMethod.GetParameters(); foreach (System.Reflection.ParameterInfo param in passedParams) System.Console.WriteLine(param.ToString()); }
如果你需要实际的价值,那么你将需要采取小型转运和分析他们恐怕。 获取转储信息的信息可以在以下urlfind:
那里有一个来自redgate的软件工具,看起来很有希望。
http://www.red-gate.com/products/dotnet-development/smartassembly/
目前,我们正在通过电子邮件收集我们的客户错误报告,我有时会遇到一些重要的数据丢失(主要是一些非常基本的variables,如当前logging中的id,所以我可以重现错误)。 我还没有testing过这个工具,但从我的理解,它收集来自堆栈的参数值和局部variables。
我不相信有一个内置的机制。 检索堆栈跟踪的每个帧,同时允许您确定跟踪中的方法,只会给出该方法的reflectiontypes信息。 没有参数信息。 我想这就是为什么一些例外,特别是ArgumentException等。 人。 提供一种机制来指定exception中涉及的参数的值,因为没有简单的方法来获取它。
理论上可以通过利用可移植可执行文件(PE)文件格式来获得variablestypes和偏移量,但是我在几年前遇到了一个试图这样做的[文档]墙。 祝你好运!
如果你可以做你正在寻找的东西,那么你将会击败.NET安全的一个组成部分。
在这种情况下,它是最好的select,它连接到debugging器或分析器(他们中的任何一个都可以访问这些值)。 前者可以附加,后者需要在程序启动之前激活。
由于最终用户是开发人员,因此可以为他们提供一个版本,以便logging所有传递的键值/参数。 并提供一个设施,以便他们可以打开/closureslogging。
我不知道这样的事情,但自己也想要。 我通常在抛出exception的时候自己做,但如果不是你的抛出,那么你可能会和我们其他人一起。
一旦你有exception,你感兴趣的两件事是System.Diagnostics.StackTrace和System.Diagnostics.StackFrame
这里有个MSDN例子
我不知道获取调用堆栈跟踪中每个函数的参数值的方法,但是一种解决scheme是捕获特定的exception(在您的示例中为KeyNotFoundException
)并将其重新抛出一个新的exception。 这可以让你联想到任何你想要的附加信息
例如:
Dim sKey as String = "some-key" Dim sValue as String = String.Empty Try sValue = Dictionary(sKey) Catch KeyEx As KeyNotFoundException Throw New KeyNotFoundException("Class.Function() - Couldn't find [" & sKey & "]", KeyEx) End Try
我很欣赏你关于错误string本地化的陈述,但是如果你的听众“主要是程序员”,那么惯例已经在一定程度上决定了对英语的理解(正确或者错误 – 但是这是另一次辩论!