我正在开发一个调用合作伙伴应用程序的COM组件的应用程序。我们是.Net,他们不是.Net我不太了解COM;我知道我们所称的组件是后期绑定的,即
obj As Object = CreateObject("THIRDPARTY.ThirdPartyObject")
然后我们在这个COM对象上调用一个方法(VB文件头部的Option Strict Off):
obj.AMethod(ByVal Arg1 As Integer, ByVal Arg2 As Integer, ByVal Arg3 as Boolean)
我有点不知道即使这个调用有效,如果我改为使用Add Reference添加对COM服务器的引用,则在创建的COM interop .dll中不存在此重载。对此方法唯一可用的调用是AMethod()
。
然而,这本身并不困扰我。困扰我的是这个电话有效一段时间,然后在几十个电话成功执行后抛出TargetParameterCountException
。
我问你,StackOverflow:
什么。的。地狱。
我唯一可以猜到的是,COM组件的文档声明这个方法是同步执行的 - 所以也许是什么负责抛出异常的东西被阻塞直到某个不确定的时间点?除此之外,我完全被这种奇怪的,更重要的是不一致的行为所困扰。
编辑#1:
我刚才记得的更重要的信息 - 电话有时会抛出ExecutionEngineException
。它只是瞥了一眼文档就意识到这是非常糟糕。做一点挖掘告诉我,后期绑定调用导致堆栈损坏,导致整个CLR崩溃。据推测,这意味着运行时会在某些时候击落不良呼叫(TargetParameterCountException
)而忽略它们(ExecutionEngineException
)其他。
编辑#2:
回答 David Lively的问题:
不幸的是,正如您所说,似乎确实存在实施中的错误。这个供应商的问题是,当我们报告错误时,他们的反应往往遵循一般形式:i)否认存在问题; ii)否认这是他们的问题; iii)拒绝修理它。这三个步骤往往会遇到令人沮丧的长时间。
答案 0 :(得分:3)
不,它不会导致堆栈损坏。 IDispatch :: Invoke()用于调用方法,参数打包在一个数组中。 IDispatch的库存实现肯定会检测到参数不匹配,它使用类型库信息来检查。但可以想象COM服务器作者自己实现了它。不完全。这是C ++黑客可能会做的事情,股票实施速度非常慢。 GC堆被破坏是在执行不完整代码时发生的事情。
答案 1 :(得分:1)
我已经有很长一段时间没有玩VB调用COM对象,但我会猜测:
如果你用太少的或太多的参数调用该对象,我会期望抛出异常,但看起来并非如此。你正在调用的方法的真正签名是什么?
在某些语言和某些情况下,当您调用方法时,参数会放在堆栈上。如果放置太多参数,则在方法完成后,无关的参数可能会保留在堆栈中。但是,这应该会导致许多其他问题。
一些可能性/考虑因素:
对象在内部抛出此异常。这应该由作者处理。
您调用的参数太多了。如上所述,如果您尝试调用的重载未在对象的类型库中发布,则实际上可能正在调用具有不同签名的其他已发布方法。如果是这种情况,我真的会期待编译错误。
您的后续调用是否发生在代码的相同部分,或者是否有不同的执行分支可能会有所不同,并导致错误?
您是从桌面应用/脚本还是网站运行此功能?如果是某个网站,您是否收到了有效的,预期的响应,或者该请求是否挂起,就像内部长时间运行的进程没有完成一样?
对象可能正在分配而不是释放资源,这可能会在这些资源耗尽时导致未定义的行为。
您是在释放呼叫之间的对象,还是每次都重新创建?
另外,re:关于后期绑定的评论:实例化COM对象的.CreateObject()
方法是正常的,可接受的方法。这不应该与这个问题有任何关系。根据您列出的例外情况,我非常倾向于认为该对象存在内部问题。
答案 2 :(得分:0)
好的,基本上 - 误报。我做错了 - 我已经从某个地方不正确地复制了一些代码而且我正在调用的东西是从不认为来支持那个重载。我觉得有趣的是,该组件并没有拒绝这种迟到的呼叫,而是完成了应该做的所有事情,至少在最初阶段。