I wish to write an attribute for a function (or class) that will catch any exception thrown and set its StackTrace
property to string.Empty
. How can I do this?
EDIT:
If I cannot accomplish this in plain C#, how can I do this in C# with PostSharp?
If a catch block cannot handle the particular exception it has caught, you can rethrow the exception. The rethrow expression ( throw without assignment_expression) causes the originally thrown object to be rethrown.
Re-throwing Exceptions The exception from the previous section propagates up the call stack and since we have no code to catch and handle the exception, it crashes. When an exception is caught, we can perform some operations, like logging the error, and then re-throw the exception.
A throw statement can be used in a catch block to re-throw the exception that is caught by the catch statement. The following example extracts source information from an IOException exception, and then throws the exception to the parent method. You can catch one exception and throw a different exception.
[Serializable]
public class MyAspect: OnExceptionAspect
{
public override void OnException(MethodExecutionArgs args)
{
throw new MyCustomException(args.Exception);
}
}
public class MyCustomException : Exception
{
public override string StackTrace
{
get
{
//return new StackTrace(10).ToString(); //Skip frames
return string.Empty; //Return empty string
}
}
}
You actually have to throw a NEW exception. @Ani's example will simply rethrow the exception already thrown with the same stack trace (it's the same because of how you got to the aspect). Throwing a new exception will "change" the stack trace but it won't erase it. If you want to erase it, you will need to throw your own class that overrides the stack trace property. passing in the old exception to the new exception will make the old exception the inner exception (if you want that)
You can accomplish this with and without PostSharp. The key is your custom exception class.
Given the following code
class Program
{
static void Main(string[] args)
{
try
{
Test1();
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace + Environment.NewLine);
}
Console.ReadKey();
}
private static void Test1()
{
try
{
Test2();
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace + Environment.NewLine);
throw e;
}
}
private static void Test2()
{
try
{
Test3();
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace + Environment.NewLine);
throw;
}
}
[MyAspect]
private static void Test3()
{
throw new InvalidOperationException();
}
}
[Serializable]
public class MyAspect : OnExceptionAspect
{
public override void OnException(MethodExecutionArgs args)
{
throw args.Exception;
}
}
the output is
at ConsoleApplication5.MyAspect.OnException(MethodExecutionArgs args) in C:\T est\Program.cs:line 69 at ConsoleApplication5.Program.Test3() in C:\Test\Program.cs:line 59
at ConsoleApplication5.Program.Test2() in C:\Test\Program.cs:line 47at ConsoleApplication5.MyAspect.OnException(MethodExecutionArgs args) in C:\T est\Program.cs:line 69 at ConsoleApplication5.Program.Test3() in C:\Test\Program.cs:line 59
at ConsoleApplication5.Program.Test2() in C:\Test\Program.cs:line 52
at ConsoleApplication5.Program.Test1() in C:\Test\Program.cs:line 34at ConsoleApplication5.Program.Test1() in C:\Test\Program.cs:line 39 at ConsoleApplication5.Program.Main(String[] args) in C:\Test\Program.cs:line 19
The original stack trace of the exception is stored in a field in the Exception
class. If you want to remove it without creating your own exception type, you can remove it via reflection like this:
[Serializable]
public sealed class NoStackTraceException : OnExceptionAspect
{
public override void OnException(MethodExecutionArgs args)
{
RemoveStackTrace(args.Exception);
}
private void RemoveStackTrace(Exception exception)
{
FieldInfo stackTraceField = typeof(Exception).GetField("_stackTrace",
BindingFlags.NonPublic | BindingFlags.Instance);
if (stackTraceField != null)
{
// sets the value of _stackTrace to null
stackTraceField.SetValue(exception, null);
}
}
}
Your exception will no longer contain the stack trace.
Edit Of course you can accomplish the same thing without PostSharp too, just do it in the catch
block.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With