I am trying to add an unhandled exception handler in .net (c#) that should be as helpfull for the \'user\' as possible. The end users are mostly programers so they just need
I'm not aware of anything like that, but have wanted it myself. I usually do it myself when throwing exceptions, but if it's not yours to throw, then you may be out with the rest of us.
I don't know a way to obtain the values of the arguments of each function in the call stack trace, but one solution would be to catch the specific exception (KeyNotFoundException
in your example) and re-throw it in a new Exception. That allows you associate any additional information you wish
For example:
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
I appreciate your statement about localising the error strings, but if your audience are 'mostly programmers' then convention already dictates a comprehension of English to some degree (rightly or wrongly - but that's another debate!)
There is a software tool from redgate out there, that looks very promissing.
http://www.red-gate.com/products/dotnet-development/smartassembly/
Currently we are collecting our customers error reports by eMail and I sometimes struggle with some important data missing (mostly some very basic variables, like the id from the current record so I can reproduce the bug). I havn't tested this tool yet, but from my understanding it does what collects the argument values and local variables from the stack.
Once you have the exception the two things you are interested in are System.Diagnostics.StackTrace and System.Diagnostics.StackFrame
There is an MSDN example here
Likewise, I've not found anything to derive the parameters automatically at runtime. Instead, I've used a Visual Studio add-in to generate code that explicitly packages up the parameters, like this:
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;
}
}
}
}
EDIT: or alternatively, by making the parameter to HandleException a params array:
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;
}
...
It's a bit of a pain generating the extra code to explicitly pass the parameters to the exception handler, but with the use of an add-in you can at least automate it.
A custom attribute can be used to annotate any parameters that you don't want the add-in to pass to the exception handler:
public UserToken RegisterUser( string userId, [NoLog] string password )
{
}
2ND EDIT:
Mind you, I'd completely forgotten about AVICode:
http://www.avicode.com/
They use call interception techniques to provide exactly this kind of information, so it must be possible.