未捕获System.Reflection.TargetInvocationException [英] System.Reflection.TargetInvocationException not being caught

查看:160
本文介绍了未捕获System.Reflection.TargetInvocationException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在解决方案之后添加注释:正在通过反射调用的方法内部引发AccessViolationException。这就是无法捕获TargetInvocationException的原因。



注意:这在IDE的外面。 引用的问题不同。



TL; DR


  1. 无法获得堆栈跟踪

  2. 无法获取内部异常

  3. 不能使用调试器(第三方库的复制保护方案会妨碍您)

  4. 对代码的任何更改都可以阻止异常的发生-意味着我无法添加日志记录来查找异常发生的位置

如何获取异常信息或以其他方式获取所需信息?



详细说明:



我遇到了一个问题,该问题发生在通过反射调用的方法中。异常本身实际上发生在被调用的方法中,但是由于该方法是通过反射调用的,因此真正的异常被包装在 System.Reflection.TargetInvocationException 中。没问题,只需捕获它并获取内部异常-除了不会捕获 System.Reflection.TargetInvocationException 。我的程序崩溃了,我在Windows事件日志中得到了转储以及条目。



Windows事件日志不包含内部异常,倾倒。
我无法将调试器附加到程序中,因为这样一来,外部库(进入反射调用所需的库)将无法运行-复制保护,您不知道。
如果我将try / catch放入违规方法中,则不会发生异常-这很糟糕。原因不固定,只是不再发生。
如果我将日志记录到令人讨厌的方法中,也会发生相同的效果-不再发生异常。



我不能使用日志记录,我可以



我不使用调试器,而在一个可以捕获该异常并记录异常的地方。



我正在使用Visual Studio 2010和dotnet 4.0。



要明确一点:当程序在Visual Studio外部运行时,try / catch不起作用,我无法在内部运行在调试器中使用Visual Studio进行调试,因为这样程序就无法到达发生异常的地步。



消除反射不是一种选择(我只在一种情况下尝试过这种方法,但异常消失了。)



被调用的方法会做很多事情,但是将其分解为较小的方法无济于事-异常消失了。



只有当我按一定顺序执行步骤时,例外情况不会一直发生,而当发生时,它总是在整个顺序中第二次出现。



在我使用的序列中,该方法几乎同时被两个线程调用-输入了特定的一堆数据,这导致报表的副本和另一个文档分别打印在两个不同的位置打印机-向每台打印机发送一份报告和文档。由于生成报告和打印文档可能需要一段时间,因此它们是在后台线程中完成的,因此用户可以继续工作。



我怀疑线程正在逐步执行在彼此的脚趾上(正在进行大量文件和数据库操作),但不知道真正发生了什么,我无法解决它。



下面的代码显示了简化的版本



是否有人对导致 System.Reflection.TargetInvocationException 不被捕获,还是捕获内部异常的另一种方法?

 尝试
Dim methode As System.Reflection.MethodInfo
methode = GetType(AParticularClass).GetMethod( OneOfManyMethods,Reflection.BindingFlags.NonPublic或Reflection.BindingFlags.Static)
Dim resultobject As Object = methode.Invoke(Nothing,Reflection) .BindingFlags.InvokeMethod或Reflection.BindingFlags.NonPubl ic或Reflection.BindingFlags.Static,Nothing,New Object(){SomeBooleanVariable,SomeStringVariable},Nothing)
结果= DirectCast(resultobject,DataSet)
异常捕获
'记录错误这里。
结束尝试


解决方案

找到了我为什么无法捕获异常:



实际的异常是AccessViolationException,如果不采取特殊步骤,则无法在dotnet 4.0中捕获该异常(如何处理AccessViolationException。



为了使事情变得更加有趣,当AccessViolationException被引发通过反射调用的方法时,Windows事件日志中只会记录TargetInvocationException,而转储中只有TargetInvocationException。



一旦设法获得真正的异常,我发现这是从非GUI线程对Application.DoEvents()的调用导致了AccessViolation。在GUI线程上调用DoEvents()可以带来足够的乐趣(使用Application.DoEvents()),更不用说从后台线程调用了。



修复后,我发现我们的第三方库(具有复制保护的第三方库)不喜欢在单独的实例中同时调用。



导致所有这些乐趣的代码一次都在GUI线程中解决,并且最初是编写的回到dotnet 1.1的时代-这解释了对DoEvents的调用。该代码已分段转换为在后台线程中通过多个不同阶段并行运行,没有一个开发人员可以全面了解该过程。


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

解决方案

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.

这篇关于未捕获System.Reflection.TargetInvocationException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆