MethodInfo.Invoke and TargetInvocationException

  • Thread starter Lasse Vågsæther Karlsen
  • Start date
L

Lasse Vågsæther Karlsen

We have a base class that relies heavily on MethodInfo.Invoke.

Often, as such things happen, exceptions are thrown in the method that
was invoked, and this pops up as a TargetInvocationException, at the
place of the Invoke command.

I have tried wrapping my call to Invoke like this:

try
{
mi.Invoke(...);
}
catch (TargetInvocationException ex)
{
throw ex.InnerException;
}

However, this changes the stack trace. Is there a way for me to re-throw
the inner exception so that Visual Studio pops up at the method being
invoked with the exception that was thrown there, instead of always
stopping in our base class?

I am working on replacing the calls to Invoke with delegates, but it's a
lot of code so it's neither quick going nor bug-free so I was hoping
there was a temporary fix for this while I rework the code.
 
P

Paul E Collins

Lasse Vågsæther Karlsen said:
Is there a way for me to re-throw the inner exception so that Visual
Studio pops up at the method being invoked with the exception that was
thrown there, instead of always stopping in our base class?

Choose "Exceptions" from the Debug menu, expand "Common Language Runtime
Exceptions", and tick the Thrown box next to
System.Reflection.TargetInvocationException. Then, whenever that
exception occurs, Visual Studio will break immediately at that point.

Eq.
 
L

Lasse Vågsæther Karlsen

Paul said:
Choose "Exceptions" from the Debug menu, expand "Common Language Runtime
Exceptions", and tick the Thrown box next to
System.Reflection.TargetInvocationException. Then, whenever that
exception occurs, Visual Studio will break immediately at that point.

Eq.

Sorry about this but I think I was a bit unclear in my original post.

Here's a short and complete program that exhibits my problem, the source
code comes first and then a description of the problem.

using System;
using System.Collections.Generic;
using System.Text;

namespace InvokeProblem
{
public class Program
{
static void Main(string[] args)
{
Test t = new Test();
t.MethodThatInvokes();
}

private class Test
{
public void MethodThatInvokes()
{
// Stop on next line
GetType().GetMethod("MethodBeingInvoked").Invoke(this,
new Object[0]);
}

public void MethodBeingInvoked()
{
// And not here
throw new Exception();
}
}
}
}

If you run this, Visual Studio will stop on the one following the
comment "// Stop on next line", and not on the one following the "// And
not here" line.

The exception being thrown is TargetInvocationException, with the
following details:

System.Reflection.TargetInvocationException was unhandled
Message="Exception has been thrown by the target of an invocation."
Source="mscorlib"
StackTrace:
at System.RuntimeMethodHandle._InvokeMethodFast(Object target,
Object[] arguments, SignatureStruct& sig, MethodAttributes
methodAttributes, RuntimeTypeHandle typeOwner)
at System.RuntimeMethodHandle.InvokeMethodFast(Object target,
Object[] arguments, Signature sig, MethodAttributes methodAttributes,
RuntimeTypeHandle typeOwner)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj,
BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo
culture, Boolean skipVisibilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj,
BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo
culture)
at System.Reflection.MethodBase.Invoke(Object obj, Object[]
parameters)
at InvokeProblem.Program.Test.MethodThatInvokes() in
C:\Dev\VS.NET\InvokeProblem\Program.cs:line 20
at InvokeProblem.Program.Main(String[] args) in
C:\Dev\VS.NET\InvokeProblem\Program.cs:line 12
at System.AppDomain._nExecuteAssembly(Assembly assembly,
String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile,
Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext
executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()

If you look through this stack trace, you'll notice that nowhere is line
26 listed in this stack trace, the line that actually threw the original
exception.

However, InnerException is set, containing this stack trace:

at InvokeProblem.Program.Test.MethodBeingInvoked() in
C:\Dev\VS.NET\InvokeProblem\Program.cs:line 26

However, if I change MethodThatInvokes to this:

public void MethodThatInvokes()
{
// Stop on next line
try
{

GetType().GetMethod("MethodBeingInvoked").Invoke(this, new Object[0]);
}
catch (TargetInvocationException ex)
{
throw ex.InnerException;
}
}

Then granted, I get the right exception (Exception in this case), but
the throw statement builds a new stack trace from the catch-block in
MethodThatInvokes.

at InvokeProblem.Program.Test.MethodThatInvokes() in
C:\Dev\VS.NET\InvokeProblem\Program.cs:line 27
at InvokeProblem.Program.Main(String[] args) in
C:\Dev\VS.NET\InvokeProblem\Program.cs:line 13
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence
assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext
executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()

So... basically, is there a way to easily re-throw the original
exception, at the original point, so that in my original source code at
the top of this post, Visual Studio stops on line 26? The reason it
doesn't stop on line 26 is of course because the exception is handled,
by the Invoke method.

I guess my question boils down to this:

in a catch block, can I re-throw the InnerException exception without
mucking up its stack trace?
 
J

Jeroen Mostert

Lasse said:
in a catch block, can I re-throw the InnerException exception without
mucking up its stack trace?
Short answer: no.

So yes, it's a good idea to restrict the use of .Invoke() to necessary cases.
 
T

Timwi Terby

I found a way to invoke methods dynamically without having the exception wrapping happening. You could try my solution, which I blogged about in my blog.

http://timwi.blog.com/2010/03/12/dynamic-invoke/



lass wrote:

Re: MethodInfo.Invoke and TargetInvocationException
28-Feb-08

Jeroen Mostert wrote

Ok, thanks

-
Lasse V?gs?ther Karlse
mailto:[email protected]
http://presentationmode.blogspot.com
PGP KeyID: 0xBCDEA2E3

Previous Posts In This Thread:

MethodInfo.Invoke and TargetInvocationException
We have a base class that relies heavily on MethodInfo.Invoke

Often, as such things happen, exceptions are thrown in the method that
was invoked, and this pops up as a TargetInvocationException, at the
place of the Invoke command

I have tried wrapping my call to Invoke like this

tr

mi.Invoke(...)

catch (TargetInvocationException ex

throw ex.InnerException


However, this changes the stack trace. Is there a way for me to re-throw
the inner exception so that Visual Studio pops up at the method being
invoked with the exception that was thrown there, instead of always
stopping in our base class

I am working on replacing the calls to Invoke with delegates, but it's a
lot of code so it's neither quick going nor bug-free so I was hoping
there was a temporary fix for this while I rework the code

--
Lasse V?gs?ther Karlse
mailto:[email protected]
http://presentationmode.blogspot.com
PGP KeyID: 0xBCDEA2E3

Re: MethodInfo.Invoke and TargetInvocationException

Choose "Exceptions" from the Debug menu, expand "Common Language Runtime
Exceptions", and tick the Thrown box next to
System.Reflection.TargetInvocationException. Then, whenever that
exception occurs, Visual Studio will break immediately at that point

Eq.

Re: MethodInfo.Invoke and TargetInvocationException
Paul E Collins wrote

Sorry about this but I think I was a bit unclear in my original post

Here's a short and complete program that exhibits my problem, the source
code comes first and then a description of the problem

using System
using System.Collections.Generic
using System.Text

namespace InvokeProble

public class Progra

static void Main(string[] args

Test t = new Test()
t.MethodThatInvokes()


private class Tes

public void MethodThatInvokes(

// Stop on next lin
GetType().GetMethod("MethodBeingInvoked").Invoke(this,
new Object[0])


public void MethodBeingInvoked(

// And not her
throw new Exception()





If you run this, Visual Studio will stop on the one following the
comment "// Stop on next line", and not on the one following the "// And
not here" line

The exception being thrown is TargetInvocationException, with the
following details

System.Reflection.TargetInvocationException was unhandle
Message="Exception has been thrown by the target of an invocation.
Source="mscorlib
StackTrace
at System.RuntimeMethodHandle._InvokeMethodFast(Object target,
Object[] arguments, SignatureStruct& sig, MethodAttributes
methodAttributes, RuntimeTypeHandle typeOwner
at System.RuntimeMethodHandle.InvokeMethodFast(Object target,
Object[] arguments, Signature sig, MethodAttributes methodAttributes,
RuntimeTypeHandle typeOwner
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj,
BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo
culture, Boolean skipVisibilityChecks
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj,
BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo
culture
at System.Reflection.MethodBase.Invoke(Object obj, Object[]
parameters)
at InvokeProblem.Program.Test.MethodThatInvokes() in
C:\Dev\VS.NET\InvokeProblem\Program.cs:line 20
at InvokeProblem.Program.Main(String[] args) in
C:\Dev\VS.NET\InvokeProblem\Program.cs:line 12
at System.AppDomain._nExecuteAssembly(Assembly assembly,
String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile,
Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext
executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()

If you look through this stack trace, you'll notice that nowhere is line
26 listed in this stack trace, the line that actually threw the original
exception.

However, InnerException is set, containing this stack trace:

at InvokeProblem.Program.Test.MethodBeingInvoked() in
C:\Dev\VS.NET\InvokeProblem\Program.cs:line 26

However, if I change MethodThatInvokes to this:

public void MethodThatInvokes()
{
// Stop on next line
try
{

GetType().GetMethod("MethodBeingInvoked").Invoke(this, new Object[0]);
}
catch (TargetInvocationException ex)
{
throw ex.InnerException;
}
}

Then granted, I get the right exception (Exception in this case), but
the throw statement builds a new stack trace from the catch-block in
MethodThatInvokes.

at InvokeProblem.Program.Test.MethodThatInvokes() in
C:\Dev\VS.NET\InvokeProblem\Program.cs:line 27
at InvokeProblem.Program.Main(String[] args) in
C:\Dev\VS.NET\InvokeProblem\Program.cs:line 13
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence
assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext
executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()

So... basically, is there a way to easily re-throw the original
exception, at the original point, so that in my original source code at
the top of this post, Visual Studio stops on line 26? The reason it
doesn't stop on line 26 is of course because the exception is handled,
by the Invoke method.

I guess my question boils down to this:

in a catch block, can I re-throw the InnerException exception without
mucking up its stack trace?

--
Lasse V?gs?ther Karlsen
mailto:[email protected]
http://presentationmode.blogspot.com/
PGP KeyID: 0xBCDEA2E3

Re: MethodInfo.Invoke and TargetInvocationException
Lasse V?gs?ther Karlsen wrote:
Short answer: no.

So yes, it is a good idea to restrict the use of .Invoke() to necessary cases.

--
J.

Re: MethodInfo.Invoke and TargetInvocationException
Jeroen Mostert wrote:

Ok, thanks.

--
Lasse V?gs?ther Karlsen
mailto:[email protected]
http://presentationmode.blogspot.com/
PGP KeyID: 0xBCDEA2E3


Submitted via EggHeadCafe - Software Developer Portal of Choice
Adding WCF Service References
http://www.eggheadcafe.com/tutorial...9-dfa51a9fab8e/adding-wcf-service-refere.aspx
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top