I am trying to get the list of calls made from the beginning of a try block to the exception. In the code below, when I fall into the Catch block, the StackTrace in the Exception object is the following :
at ConsoleApplication.Program.MethodC() / at
ConsoleApplication.Program.Main(String[] args).
This is totally expected, but doesn't help me to get the history of calls. Does anybody have an idea on how I could do this?
static void MethodA() { }
static void MethodB() { }
static void MethodC() { throw new Exception(); }
static void Main(string[] args)
{
try
{
MethodA();
MethodB();
MethodC();
}
catch (Exception e)
{
// Get list of calls
throw;
}
}
I was surprised to see that the StackTrace property of the Exception object isn't StackTrace object. Is there any reason for this?
In the end, the purpose of all this is simple. If an exception is thrown during the execution of the code, I want to look at the meta data (attribute) of each of the methods called.
As I understand your question, you want to be able to know which methods was called before MethodC in your try block. I don't think you can do that without adding code to your methods.
When MethodA finishes executing, it is no longer on the stack, so there is nowhere you can get the information from. Same goes for MethodB, and only MethodC is on the stack when the Exception occurs.
It seems you're not going to be able to get a stack trace for each method called with the try block unless you add custom logging code to each method. However, you can create a System.Diagnostics.StackTrace option easily from an exception simply by passing the Exception object to the constructor. This will make available all the information about the stack trace including whether the exception was thrown from MethodA/MethodB/MethodC, which might be at least somewhat helpful to you.
Example code:
static void MethodA() { }
static void MethodB() { }
static void MethodC() { throw new Exception(); }
static void Main(string[] args)
{
try
{
MethodA();
MethodB();
MethodC();
}
catch (Exception e)
{
System.Diagnostics.StackTrace callStack = new System.Diagnostics.StackTrace(e);
System.Diagnostics.StackFrame frame = null;
System.Reflection.MethodBase calledMethod = null;
System.Reflection.ParameterInfo[] passedParams = null;
for (int x = 0; x < callStack.FrameCount; x++)
{
callStack.GetFrame(x);
calledMethod = frame.GetMethod();
passedParams = calledMethod.GetParameters();
foreach (System.Reflection.ParameterInfo param in passedParams)
System.Console.WriteLine(param.ToString());
}
}
}
(You can see this SO thread for the original answer containing the code. I've just slightly modified it.)
Hope that's at least a partial solution to your question.
You can easily get a StackTrace object from anywhere in your code but as has already been pointed out you can not get the full history of method calls.
Related
I have not come across any Question/Solution in Stackoverflow for this question which has got some high number of votes.
So I thought I will ask it again here.
How to handle or what to do if there is an Exception in Dispose() method.
Shall we Log it or if I Rethrow the Exception, will it get Rethrown. I might want to Rethrow it so that I come to know I made a mistake somewhere in my Dispose()
Even If we suppose it does get Rethrown, will it be a good practice to rethrow it?
In most (but not all) cases, your exception handlers should be at the code entry point.
Just let the exception bubble up, like this.
public static class Program
{
public static void Main()
{
try
{
using (new QuestionableCodeAtBest()) {}
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
}
}
class QuestionableCodeAtBest : IDisposable
{
const int TotalHands = 2;
public void Dispose()
{
var handsThatAreClapping = 0;
Console.WriteLine($"What is the sound of no hands clapping?: {TotalHands / handsThatAreClapping}");
}
}
Is there any way to force that the caller could override the catch ?
i.e.
void ParentMethod()
{
try
{
child_method();
}
catch(Exception e)
{
MessageBox.Show("parent");
}
}
void child_method()
{
try
{
smth();
}
catch(Exception e)
{
MessageBox.Show("child");
}
}
so, when smth throws exception, instead of "child", i could override that catch with parent, and show i.e. parent.
Note 1: I am in a case, where I don't control child. However, for the sake of the answer completion, you can still answer for the case when child is controlled.
Note 2: I nowhere mentioned that I have classes or inheritance. Please avoid answers for virtual/override things. I know that.
If the child method's code is also owned/controlled/has access to, by the person/group who owns/controls the code for parent method, then you can do few things -
if there's always a parent method to call this child method and that, child method is not going to be on its own (by your design), you can ignore the try-catch in child and have the parent handle whatever they want to.
If (not #1) then its true from the above comment.
Ideally, and this is purely from my experience and opinion, if a method needs try-catch (based on what it does would qualify for it), catch block should catch the exception, do something like log it, and throw unless thats the last calling method.
There's not a way to enforce that a called method must rethrow any raised exceptions. The calling method is free to swallow whatever exception it wants.
That said, the way to catch the exception in the parent method also is to either rethrow the original exception or a new exception:
void child_method()
{
try
{
smth();
}
catch(Exception e)
{
MessageBox.Show("child");
//or: throw new Exception("Exception thrown in child");
}
}
Short answer is no.
But there I guess you misunderstood few things about Object Oriented Programming.
So you can override a method with another method with same name and different prototype if you want more configuration or different behaviour.
You can inherite from a class and override methods to share a common part and adjust whatever you want.
Ok so there you want a common part parent that would contain the try catch section.
So there you got a really different approach from what you did, but if I understood well quite suite what you want.
using System;
namespace ConsoleApp4
{
class Program
{
static void Main(string[] args)
{
VirtualTest test1 = new Test1();
test1.ParentMethod();
VirtualTest test2 = new Test1();
test2.ParentMethod();
Console.ReadKey();
}
}
abstract class VirtualTest
{
public void ParentMethod()
{
try
{
ChildMethod();
}
catch
{
Console.WriteLine("parent");
}
}
protected abstract void ChildMethod();
}
class Test1 : VirtualTest
{
protected override void ChildMethod()
{
try
{
throw new ArgumentException("A message");
}
catch (ArgumentException e)
{
Console.WriteLine(e.Message);
throw; //Here is a way to handle more specificly some
//errors but still throwing and keeping the original stacktrace
}
}
}
class Test2 : VirtualTest
{
protected override void ChildMethod()
{
throw new NotImplementedException();
}
}
}
In that case you also have more control of what you're catching at which level and you can decide wether you want to deal with it or not.
The finer level you handle the Exception the better.
Also in that example Parents are actually parents and Children are actually childrend in a POO way.
I having some classes related like the following domain drawing:
The Requestcontroller is running a loop in a ThreadPool, which on received messages will handle them and call some methods in FooClass, which then should throw exceptions if anything goes wrong.
In example (in some way pseudo-code):
class RequestController
{
private FooClass fooClass;
public RequestController(ref FooClass fooClass)
{
this.fooClass = fooClass;
}
void OnResponseReceived()
{
try
{
this.fooClass.ProcessingRequest("id", "requestType", 13);
}
catch(Exception ex)
{
Debug.Fail(ex.Message);
}
}
}
class FooClass
{
private object myObj;
[...]
public void ProcessingRequest(string id, string type, int count)
{
try
{
myObj.MethodAsync(id, type, RequestFailedCB, myObj);
//This method throws an Exception, that I want to be handled by RequestController class based on the Exception
}
catch(Exception)
{
throw;
}
}
}
So, my problem is that the Async method (MethodAsync in FooClass) will fail, and throw an Exception in FooClass, but it's giving me "Unhandle Exception". What I want is that the Requestcontroller is calling the method of FooClass, and if the async method that has been invoked in the FooClass.ProcessingRequest fails and throws an exception, which my RequestController should react on, and sending a message further on in the system, that there has been an error in the response received.
Would it be an idea to make the ProcessingRequest as and Callback method, or are there any better way to solve this purpose???
EDIT:
#KC-NH without posting pages of complex code, I'll try to get closer to the point.
As commented I forgot to mention that the project i .net 4 target. And the example posted in the FooClass method, is actually calling a .BeginTransfer of the UCMA 4 api, which I want to catch if it fails, and let the RequestController send a message about the failure further on in the system. The .BeginTransfer method returns IAsyncResult, and needs a Callback as one of the parameters.
The exception that the system throws, is inside this CB, but if I try to throw that exception from the Callback, I'm getting "Unhandled Exception", probably cuz the callback doesn't know where to throw that exception??
[.NET 4.5 specific solution]
You should always await async calls. await will rethrow exceptions as expected. This should correct your problem:
class RequestController
{
private FooClass fooClass;
public RequestController(ref FooClass fooClass)
{
this.fooClass = fooClass;
}
public async void OnResponseReceived()
{
try
{
await fooClass.ProcessingRequest();
}
catch (Exception ex)
{
System.Diagnostics.Debug.Fail(ex.Message);
}
}
}
public class FooClass
{
private object myObj;
public async Task ProcessingRequest()
{
await myObj.MethodAsync(id, type, RequestFailedCB, myObj);
}
}
I spoke with one of my colleagues today. He suggested that I used an EventHandler, to raise an event on exception catched in the callback method inside my FooClass. So the solution looks like this:
FooClass RequestFailedCB throws an exception
In RequestFailedCB the exception gets catched, and raising a ErrorEvent on my EventHandler.
The RequestController now gets information, that an event has been raised.
The RequestController will handle the error throw by the event, based on EventArgs and sender object, and can now send that error further on in the system.
Problem solved :) Thanks for all inputs.
I have the following code:
[Serializable]
class ExceptionAspectHandler:OnExceptionAspect
{
public override void OnException(MethodExecutionArgs args)
{
Console.WriteLine("{0}", args.Exception);
args.FlowBehavior = FlowBehavior.Continue;
}
}
[OnExceptionAspect]
public static void divide()
{
int n = Convert.ToInt32(Console.ReadLine());
var a = 100 / n; //the exception happens here
Console.WriteLine("it should get here");
}
Using FlowBehavior.Continue ends divide() and returns to the main() method.
Remember, the OnException aspect wraps your code in a try/catch so the code will continue from the catch (instead of rethrowing) and it's behavior will default to return. Are you wanting it to continue from where it threw the exception? If so, you need to explicitly wrap that line in a try/catch yourself.
Please read http://www.sharpcrafters.com/blog/post/Day-6-Your-code-after-PostSharp.aspx for more details.
The attribute used in divide() method should be ExceptionAspectHandler (you've created), not OnExceptionAspect.
I want to get function name of the exception thrown from dll in asp.net.
You can create a StackTrace class from the exception and analyze the frames.
For example:
public void Throw()
{
throw new MyException();
}
public void CallThrow()
{
Throw();
}
[Test]
public void GetThrowingMethodName()
{
try
{
CallThrow();
Assert.Fail("Should have thrown");
}
catch (MyException e)
{
MethodBase deepestMethod = new StackTrace(e).GetFrame(0).GetMethod();
string deepestMethodName = deepestMethod.Name;
Assert.That(deepestMethodName, Is.EqualTo("Throw"));
}
}
You should be able to make use of the Stack Trace
Exception.StackTrace Property
StackTrace Class
Represents a stack trace, which is an
ordered collection of one or more
stack frames.
StackFrame Class
A StackFrame is created and pushed on
the call stack for every function call
made during the execution of a thread.
The stack frame always includes
MethodBase information, and optionally
includes file name, line number, and
column number information.
StackFrame information will be most
informative with Debug build
configurations. By default, Debug
builds include debug symbols, while
Release builds do not. The debug
symbols contain most of the file,
method name, line number, and column
information used in constructing
StackFrame objects.
You can try stacktrace object with the help of system.diagnostic namespace here is the linqpad testing source code that you can try out.
void Main()
{
try {
test();
}
catch(Exception ex) {
StackTrace st = new StackTrace();
st.GetFrame(1).GetMethod().Name.Dump();
}
}
// Define other methods and classes here
public void test()
{
throw new NotImplementedException();
}
Checkout StackTrace.GetFrame Method