5

NOTE ADDED AFTER SOLUTION: An AccessViolationException was being thrown inside the method called by reflection. This was the reason the TargetInvocationException couldn't be caught.

NOTE: This is OUTSIDE of the IDE. The referenced question is NOT the same.

TL;DR

  1. Can't get a stack trace
  2. Can't get inner exceptions
  3. Can't use debugger (copy protection scheme of a third party library gets in the way)
  4. Any changes to the code prevent the exception from occurring - means I can't add logging to find out where the exception occurrs

How can I get the exception to be caught or get the needed information some other way?

Long description:

I am having a problem with an exception that occurs in a method that gets called by reflection. The exception itself actually occurs in the called method, but since the method is called by reflection, the real exception gets wrapped in a System.Reflection.TargetInvocationException. No problem, just catch it and get the internal exception - except the System.Reflection.TargetInvocationException doesn't get caught. My program crashes, and I get a dump along with an entry in the Windows event log.

The Windows event log doesn't contain the internal exceptions, and neither does the dump. I can't attach a debugger to the program because then an external library (which is needed to get to the reflection call) won't run - copy protection, don't you know. If I put a try/catch into the offending method, the exception doesn't occur - which is bad. The cause isn't fixed, it just doesn't happen any more. The same effect happens if I put logging into the offending method - the exception doesn't occur any more.

I can't use logging, I can't use a debugger, and in the one place where I could catch the exception and log it the exception doesn't get caught.

I'm using Visual Studio 2010 and dotnet 4.0.

To make it clear: The try/catch doesn't work when the program is run outside of Visual Studio, and I can't run it inside of Visual Studio in the debugger because then the program can't reach the point where the exception occurs. This is NOT within the IDE.

Eliminating the reflection isn't an option (I've tried it for just the one case, and the exception goes away.)

The method being called does a lot of stuff, but breaking it down into smaller methods doesn't help - the exception just goes away.

The exception doesn't occur all the time, only when I do a certain sequence of steps - and when it occurs then it is always on the second time through the whole sequence.

In the sequence I am using, the method gets called by two threads almost simultaneously - a particular bunch of data gets entered, which causes a copy of a report and another document to be printed on two separate printers - one report and document to each printer. Since generating the reports and printing the document can take a while, they are done on threads in the background so the user can continue working.

I suspect that the threads are stepping on each others toes (lots of file and database manipulations going on) but without knowing what is really happening I can't fix it.

The code below shows a simplified version of the call by reflection.

Does any one have a suggestion as to what may be causing the System.Reflection.TargetInvocationException to not be caught, or maybe an alternative way to catch the inner exception?

Try
    Dim methode As System.Reflection.MethodInfo
    methode = GetType(AParticularClass).GetMethod("OneOfManyMethods", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Static)
    Dim resultobject As Object = methode.Invoke(Nothing, Reflection.BindingFlags.InvokeMethod Or Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Static, Nothing, New Object() {SomeBooleanVariable, SomeStringVariable},  Nothing)
    result = DirectCast(resultobject, DataSet)
Catch ex As Exception
    'Log the error here.
End Try
Community
  • 1
  • 1
JRE
  • 337
  • 3
  • 14
  • possible duplicate of [Why is TargetInvocationException treated as uncaught by the IDE?](http://stackoverflow.com/questions/2658908/why-is-targetinvocationexception-treated-as-uncaught-by-the-ide) – Bradley Uffner Apr 16 '15 at 17:43
  • 1
    Not a duplicate because this occurs outside of the IDE. – JRE Apr 16 '15 at 17:44
  • 1
    This is a lot of text, with very little information that would allow anyone to even guess the reason. There is no stack trace. There is no code that is actually part of your problem. You mention things being run in threads, but don't show how. Please include the relevant information. – Alex Apr 16 '15 at 18:18
  • 3
    @Alex: That is exactly the problem. I can't get a stack trace that goes any further than System.Reflection.TargetInvocationException. I'm not asking for help in fixing my code. I'm asking for help in getting the information that would let me fix it myself. – JRE Apr 16 '15 at 19:02
  • I use `System.Reflection.MethodInfo.GetCurrentMethod.ToString` inside my `Catch` block **NOT** outside of it and it work's just fine... Why are you `invoking` , it's not doing anything anyways... – Trevor Apr 16 '15 at 19:13
  • @436f6465786572 - Yes, the method actually gets called and invoked. In most cases, everything works fine, but sometimes it doesn't and I get the given exception. ToString has nothing to do with the problem at all. – JRE Apr 16 '15 at 19:16
  • I didn't say the `ToString` does, we add that to log the exception... – Trevor Apr 16 '15 at 19:17
  • Yeah, except the exception isn't caught, so I can't log it. That's what the whole question is about - why doesn't the try/catch catch anything? – JRE Apr 16 '15 at 19:18

2 Answers2

8

Found the reason why I couldn't catch the exception:

The actual exception was an AccessViolationException, which can't be caught in dotnet 4.0 without taking special steps (How to handle AccessViolationException.)

To make things more fun, when AccessViolationException gets thrown in a method called by reflection, only a TargetInvocationException gets logged in the Windows event log, and only the TargetInvocationException is available in the dump.

Once I managed to get the real exception, I found that that it was a call to Application.DoEvents() from a non-GUI thread that caused the AccessViolation. DoEvents() can cause enough fun when called on the GUI-Thread (Use of Application.DoEvents()), let alone when called from a background thread.

Once that was fixed, I found that our third party library (the one with the copy protection) doesn't like being called simultaneously in separate instances. Fixing that was a matter of a synclock in the right place.

The code causing all of this fun was at one time all in the GUI-Thread, and was originally written back in the days of dotnet 1.1 - this explains the call to DoEvents. The code has been converted piece-wise to run in parallel in background threads through several different stages, with no one single developer having a complete overview of the process.

Community
  • 1
  • 1
JRE
  • 337
  • 3
  • 14
  • How did you end up debugging this? We're seeing the same issue with just TIE ending up in the Windows event log – ChaseMedallion Dec 07 '15 at 17:46
  • Add Try/catch (if you don't already have it) then follow the instructions here (http://stackoverflow.com/a/4759831/3945058) to enable catching the "corrupted state" exceptions. – JRE Dec 08 '15 at 08:36
  • Hi, this seems to be [my problem too](http://stackoverflow.com/q/39954552/1488067), I noticed the `AccessViolationException` inside the windows error reporting log just after my exception. One thing is not completely clear, if you can clarify it: did your the exception actually occur at the point shown with the stack trace, or did it occur at some completely different thread and only appeared to fail inside your method? How did you manage to get the "real exception"? – Lou Oct 10 '16 at 09:40
  • 1
    @Lousy: I finally managed to catch the exception by following the instructions in the answer that I linked to in this answer and in the first comment I made to this answer. There is a directive that goes in your app.config that tells .Net to let you catch all exceptions. Then, you can catch and log the exception including the stack trace. – JRE Oct 10 '16 at 09:45
  • @JRE: thanks! So, the `TargetInvocationException` is a kind of a red herring then? The actual exception is unrelated? Because, if I got it right, I need to decorate the method which contains the actual `try/catch`, just where the exception happens, with the `[HandleProcessCorruptedStateExceptions]` attribute, and I am not sure how to do that if I don't know the actual method in the first place. Or is the app.config setting enough? – Lou Oct 10 '16 at 09:51
  • Ok, got it, seems like [the attribute should be enough](https://msdn.microsoft.com/en-us/library/dd638517(v=vs.110).aspx). – Lou Oct 10 '16 at 09:57
  • 1
    The app.config setting is all you need. And, yes, the TargetInvocationException was a red herring. It got logged in the Windows event log, but the real problem was something else entirely. The TargetInvocationException only tells you that an error occurred in an Invoked method, but it isn't the error itself. – JRE Oct 10 '16 at 10:08
-1

I am not sure I can replicate your issue, but this is how we get it and it work's just fine...

 Try
   'YOUR CODE'
 Catch ex As Exception
    'This is where we grab it from... It needs to be in this block to work...
    System.Reflection.MethodInfo.GetCurrentMethod.ToString
 End Try

Let me know how it work's out for you?

Trevor
  • 7,777
  • 6
  • 31
  • 50
  • As I said, the catch doesn't catch anything, the program just crashes. All I get is a Windows Event log entry that says a program crashed and tells me what kind of exception it was. – JRE Apr 16 '15 at 19:21
  • So it's a different type of exception then, that's why it's not being caught... Show what code is in that block... – Trevor Apr 16 '15 at 19:35
  • Can't, it is several hundred lines long and includes calls to other methods. Ancient sins that I didn't commit but have to live with. It is also most definitely System.Reflection.TargetInvocationException, but it is being caused by something inside the reflected method. The type doesn't matter, anyway - Catch ex as Exception should catch every kind of exception. – JRE Apr 16 '15 at 19:41