注意:这是IDE的外部. The referenced question is NOT the same.
TL; DR
>无法获得堆栈跟踪
>无法获得内部异常
>不能使用调试器(第三方库的复制保护方案妨碍)
>对代码的任何更改都会阻止异常发生 – 意味着我无法添加日志记录以找出发生异常的位置
详细描述:
我遇到的问题是在一个被反射调用的方法中发生的异常.异常本身实际上发生在被调用的方法中,但由于该方法是通过反射调用的,因此真正的异常包含在System.Reflection.TargetInvocationException中.没问题,只需捕获它并获取内部异常 – 除了System.Reflection.TargetInvocationException没有被捕获.我的程序崩溃,我得到一个转储以及Windows事件日志中的条目.
Windows事件日志不包含内部异常,也不包含转储.
我无法将调试器附加到程序中,因为外部库(需要进入反射调用)将无法运行 – 复制保护,您知道吗?
如果我将一个try / catch放入有问题的方法中,则不会发生异常 – 这很糟糕.原因并不固定,只是不再发生.
如果我将登录放入有问题的方法,则会发生同样的效果 – 不再发生异常.
我不能使用日志记录,我不能使用调试器,并且在我可以捕获异常并记录它的一个地方,异常不会被捕获.
我正在使用Visual Studio 2010和dotnet 4.0.
为了说清楚:当程序在Visual Studio之外运行时,try / catch不起作用,我无法在调试器中的Visual Studio内运行它,因为那时程序无法到达异常点发生.这不在IDE中.
消除反射不是一种选择(我只针对一种情况尝试过,异常就消失了.)
被调用的方法做了很多事情,但是把它分解成更小的方法并没有帮助 – 例外就消失了.
异常不会一直发生,只有当我执行某一系列步骤时 – 并且当它发生时,它总是在整个序列中第二次发生.
在我使用的序列中,该方法几乎同时由两个线程调用 – 输入一组特定的数据,这会导致报告的副本和另一个文档打印在两个单独的打印机上 – 每个打印机一个报告和文档.由于生成报告和打印文档可能需要一段时间,因此它们在后台的线程上完成,因此用户可以继续工作.
我怀疑线程正在踩着彼此的脚趾(正在进行大量的文件和数据库操作),但不知道实际发生了什么,我无法解决它.
是否有人建议可能导致System.Reflection.TargetInvocationException未被捕获,或者可能是另一种捕获内部异常的方法?
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
实际的异常是AccessViolationException,如果不采取特殊步骤(How to handle AccessViolationException.),则无法在dotnet 4.0中捕获
为了使事情变得更有趣,当在反射调用的方法中抛出AccessViolationException时,只会在Windows事件日志中记录TargetInvocationException,并且转储中只有TargetInvocationException可用.
一旦我设法获得真正的异常,我发现它是从导致AccessViolation的非GUI线程调用Application.DoEvents().在GUI-Thread(Use of Application.DoEvents())上调用时,DoEvents()可以带来足够的乐趣,更不用说从后台线程调用了.
一旦修复,我发现我们的第三方库(具有复制保护的库)不喜欢在不同的实例中同时调用.修复这是一个在正确的地方合并的问题.
导致所有这些乐趣的代码一次都在GUI-Thread中,并且最初是在dotnet 1.1的时代写回来的 – 这解释了对DoEvents的调用.代码已逐段转换为在后台线程中并行运行几个不同的阶段,没有一个开发人员对该过程有完整的概述.