I know. A similar question has already asked.
but I haven't got the exact solution from that.
I have a button click event in which I have a method FillCombo()
.
Button Click event
private void button1_Click(object sender, EventArgs e)
{
try
{
cmbTemplates.Items.Clear();
lstFiles.Clear();
FillCombo();
}
catch (Exception ex)
{
MethodBase site = ex.TargetSite;
Log(ex.ToString(), site == null ? null : site.Name);
}
}
When I debugged, I found that the exception occurs from FillCombo()
method. After that I get the value of site.Name
as WinIOError
instead of FillCombo
.
I tried another method GetExecutingMethodName()
which was answered by Chris Gessler in How to get the name of the method that caused the exception question. So I tried sending the name of method that caused exception using GetExecutingMethodName()
method
Log(ex.ToString(), GetExecutingMethodName());
But I got the result as System.Windows.Forms.Control.OnClick
instead of FillCombo
.
How do I get the actual name of method that caused exception?
The throws keyword is used to declare which exceptions can be thrown from a method, while the throw keyword is used to explicitly throw an exception within a method or block of code. The throws keyword is used in a method signature and declares which exceptions can be thrown from a method.
The caller has to handle the exception using a try-catch block or propagate the exception. We can throw either checked or unchecked exceptions. The throws keyword allows the compiler to help you write code that handles this type of error, but it does not prevent the abnormal termination of the program.
The primary method of handling exceptions in PHP is the try-catch. In a nutshell, the try-catch is a code block that can be used to deal with thrown exceptions without interrupting program execution. In other words, you can "try" to execute a block of code, and "catch" any PHP exceptions that are thrown.
.net supports getting the stack trace information from an exception. You could filter out the method (and its name) by examining the first frame (origin).
new StackTrace(ex).GetFrame(0).GetMethod().Name
This would probably give you exactly the same as the targetsite (the win io), but you can examine the stacktrace for the first user code, or the first frame in your type, or whichever your needs.
For example, getting the name of the culprit thrower in your current assembly:
var s = new StackTrace(ex);
var thisasm = Assembly.GetExecutingAssembly();
var methodname = s.GetFrames().Select(f => f.GetMethod()).First(m => m.Module.Assembly == thisasm).Name;
It is important to understand what is meant by "the method that threw the exception". When an exception occurs, there is a specific method that is actually executing. Just because at some point before the exception, you called your own FillCombo()
method, that doesn't mean that's the method that threw the exception.
The FillCombo()
method will however (in the case you care about here) be in the stack trace. That's why it's useful to log the entire stack trace. Indeed, I just generally log the whole Exception
object (i.e. ex.ToString()
, or just pass the exception object to string.Format()
or similar which will call ToString()
for you). This will include the exception type, the message, the entire stack trace, and even inner exception information if present.
The code you got from the other question, for the GetExecutingMethodName()
method, is not really all that useful IMHO. You'll note that what it really does is crawl through the stack trace of the current executing location, looking for the first method that is declared in a type other than the one where the GetExecutingMethodName()
was declared.
This is wrong for your purpose for two reasons:
Click
event handler is declared. This means the event handler method is ignored, and so you get the caller of that method, which is the Control.OnClick()
method (i.e. the method that actually raises the event).Frankly, I find that particular answer odd, because .NET already provides an API for retrieving the MethodInfo
of the currently executing method: MethodBase.GetCurrentMethod. And this is way more reliable than the code Chris Gessler wrote.
button1_Click()
method. But you already know that, because the code you're writing to handle the exception is in that method.
If you want to know the name of the method in your currently executing method that was called before the exception occurred, you can combine the two techniques: get the name of the currently executing method, and then pass that to a method that takes both that and the stack trace string from the Exception
object, and let that method parse the stack trace string to find the frame just before the currently executing method in the trace.
It's a bit of a pain, but it could be done. Here's an example of what that would look like (simple proof-of-concept console program):
static void Main(string[] args)
{
try
{
CallForException();
}
catch (Exception e)
{
Console.WriteLine("Exception occurred calling {0} method", GetCallForExceptionThisMethod(MethodBase.GetCurrentMethod(), e));
}
}
private static string GetCallForExceptionThisMethod(MethodBase methodBase, Exception e)
{
StackTrace trace = new StackTrace(e);
StackFrame previousFrame = null;
foreach (StackFrame frame in trace.GetFrames())
{
if (frame.GetMethod() == methodBase)
{
break;
}
previousFrame = frame;
}
return previousFrame != null ? previousFrame.GetMethod().Name : null;
}
private static void CallForException()
{
DoActualException();
}
private static void DoActualException()
{
throw new NotImplementedException();
}
Finally, keep in mind that due to method inlining and other optimizations, even a full stack trace may have some irregularities in it, including not even having the actual name of the method where the exception was thrown. That's another reason that logging the entire Exception
object is usually much more useful; the more context, the more likely you are to be able to reconstruct what happened.
Just try this:
var methodFullName = exception.TargetSite.ReflectedType.FullName
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