1

I've noticed that the "Just My Code"/"Break On Unhandled Exeptions" feature of debugging isn't working when dynamically invoking a method using the .net Framework 4.0 or higher. If I change the project to use the 3.5 framework, it runs just fine.

Given this example Command Line App:

using System;

namespace InvokeFail
{
    class Program
    {
        static void Main(string[] args)
        {
            HandledExceptions();
        }
        public static void HandledExceptions()
        {
            try
            {
                Fail();
            }
            catch (NotImplementedException)
            {
                // handle it amazingly well
            }

            try
            {
                InvokeFail();
            }
            catch (NotImplementedException)
            {
                // handle it amazingly well
            }
        }

        private static void Fail()
        {
            throw new NotImplementedException();
        }

        private static void InvokeFail()
        {
            try
            {
                typeof(Program).GetMethod("Fail", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)
                                      .Invoke(null, null);
            }
            catch (System.Reflection.TargetInvocationException ex)
            {
                throw ex.InnerException;
            }
        }
    }
}

And these VS Debug Options:

VS Options Debugging Dialog

VS Debugger Exceptions Window

Here is a picture of where the debugger stops, and it's call stack: Debugger No Debuggy

Daryl
  • 18,592
  • 9
  • 78
  • 145
  • 2
    An assumption of a bug in the unit test runner should always be last on your list. You expected the exception to be thrown by the Fail() method. It wasn't, you've got a bug in your Reflection code which causes a NullReferenceException. You need BindingFlags.NonPublic for private methods. – Hans Passant May 27 '14 at 18:20
  • @HansPassant, Thanks for catching that. When I was creating the sample error I found that bug and fixed it and thought I had updated the SO question. The question is still valid however. Running that test sample still has the debugger break in the Fail Method, when called reflectively... – Daryl May 27 '14 at 18:54
  • Hmm, works fine on my machine. Something else you forgot to update? – Hans Passant May 27 '14 at 19:12
  • @HansPassant I've converted it to a Console App and updated the question, same issue. Wondering if it has to do with VS 2013? – Daryl May 27 '14 at 19:34
  • @HansPassant I have finally figured out its a .net 4.0+ issue. The 3.5 Framework behaves as expected. – Daryl May 27 '14 at 19:43
  • Hmm, very doubtful. I tested on 4.5.1 just like you did. – Hans Passant May 27 '14 at 20:21
  • @Daryl - My guess is that you are actually looking at this backwards. I'm thinking that this was actually a bug in 3.5 that allowed it to work, and they fixed it in 4.0, or maybe not a bug but a just a change in behavior that Reflected calls. It seems to me that your code actually is unhandled, because the invoker has translate the exception. – Erik Funkenbusch May 27 '14 at 20:25
  • @ErikFunkenbusch Can you convert your comment to an answer and reference this: http://stackoverflow.com/questions/4117228/reflection-methodinfo-invoke-catch-exceptions-from-inside-the-method? I'll mark it as the answer. – Daryl May 27 '14 at 20:42
  • @Daryl - Go ahead and answer your own question, I don't consider my comment to be authoritative enough to be an answer. – Erik Funkenbusch May 27 '14 at 21:46

1 Answers1

0

Apparently there was a purposeful change in the .net framework with the 4.0 version going forward.

See here for a definition of the bug and possible work arounds.

This was just a comment in this question but it makes sense:

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.

Community
  • 1
  • 1
Daryl
  • 18,592
  • 9
  • 78
  • 145