25

I have some code that is using reflection to pull property values from an object. In some cases the properties may throw exceptions, because they have null references, etc.

object result;
try
{
    result = propertyInfo.GetValue(target, null);

}
catch (TargetInvocationException ex)
{
    result = ex.InnerException.Message;
}
catch (Exception ex)
{
    result = ex.Message;
}

Ultimately the code works correctly, however when I am running under the debugger:

When the property throws an exception, the IDE drops into the debugger as if the exception was uncaught. If I just hit run, the program flows through and the exception comes out as a TargetInvocationException with the real exception in the InnerException property.

How can I stop this from happening?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jason Coyne
  • 6,509
  • 8
  • 40
  • 70

2 Answers2

30

This seems to be "by design". What happens is that you likely have menu ToolsOptionsDebuggingGeneralEnable Just My Code enabled.

As How to: Break on User-Unhandled Exceptions states:

The DebugExceptions dialog shows an additional column (Break when an exception is User-unhandled) when "Enable Just My Code" is on.

Essentially this means that whenever the exception is leaving the boundary of your code (and in this case, it falls through down to the .NET framework reflection code), Visual Studio breaks because it thinks that the exception has left the user code. It doesn't know that it will return into the user code later in the stack.

So there are two workarounds: Disable Just My Code in menu ToolsOptionsDebuggingGeneral or Remove the check box from the User-unhandled .NET Framework exceptions in menu DebugExceptions dialog.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Kirill Osenkov
  • 8,786
  • 2
  • 33
  • 37
  • Indeed, this helped: I had somewhere a string formatting error (tried to display a TimeSpan in int format, instead of the number of days) and got this error. Inner exception: incorrect format string. But how to find where this formatting was done. When I checked the "Enable just my code" the uncaught exception immediately showed that this was the problem. – Harald Coppoolse Jul 14 '15 at 07:19
4

EDIT: I've just tried this myself, and it looks like reflection is treated slightly differently. You might want to think of a reflection call as starting a new level of "handled" as far as the debugger is concerned: nothing is catching that exception before it gets translated and rethrown as a TargetInvocationException, so it breaks in. I don't know if there's any way of inhibiting that - but does it happen very often? If you're regularly performing lots of operations which result in exceptions, you might want to reconsider your design.


Original answer

Go to Debug / Exceptions... and see what the settings are. You'll see this behaviour if TargetInvocationException (or anything higher in the hierarchy) has the "Thrown" tickbox checked.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • The use case is a "watch window" for variables that my app is using. To be able to show the user the state of what is going on in the application. So it only happens when the user is requesting the watch window to be updated. At runtime its not really a problem as the exception is ultimately caught, but during development its a huge pain because it keeps breaking me out of running! – Jason Coyne Apr 17 '10 at 15:47
  • @Jason: Yes, I can see that being a pain. I don't know of a way round it I'm afraid. For most situations it's probably the right behaviour. – Jon Skeet Apr 17 '10 at 15:56
  • Why would this be the right behavior? If I said to catch it, isn't it caught? – Jason Coyne Apr 17 '10 at 18:11
  • @Jason: The problem is that you're not really specifying what kind of exception you want caught in the way that you normally would. The translation layer is effectively hidden from you by the fact that you're using reflection. You can't explicitly target one kind of exception being thrown by the caller. – Jon Skeet Apr 17 '10 at 18:26
  • How is catch(Exception) not catching everything? – Jason Coyne Apr 17 '10 at 18:48
  • @Jason: You've missed my point: that `catch(Exception)` isn't saying "I want to catch any exception thrown by reflection" - the `TargetInvocationException` is already doing that. The point is that you don't get to say, "I want to catch IOException" when you use reflection; you just have to catch everything by using `TargetInvocationException`. – Jon Skeet Apr 17 '10 at 19:08
  • A long time passed, but I think you still missed my point. I said catch TargetInvocationException. I said catch Exception. All exceptions, regardless of source, or reflection, or not, should be caught. The IDE behaves as if the exception were uncaught. – Jason Coyne Oct 01 '13 at 16:55
  • @JasonCoyne: Yes, and my edited answer reflects that. – Jon Skeet Oct 01 '13 at 20:38
  • @JasonCoyne - You aren't really understanding the problem. When an exception gets thrown in the property, it is unhandled there, in the property. The `MethodInfo` invoker (which gets called from `PropertyInfo.GetProperty()` translates the real thrown exception into a TargetInvocationException. So you're not handling the real exception, you're handling the wrapped exception. The real exception (which is now wrapped in `TargetInvocationException`) was unhandled. – Erik Funkenbusch May 27 '14 at 21:40
  • If you compile with the 3.5 framework, this does work as expected. – Daryl May 28 '14 at 12:52