COM 方法调用在 C#、VB.NET 中失败,但在 Python 中有效

Posted

技术标签:

【中文标题】COM 方法调用在 C#、VB.NET 中失败,但在 Python 中有效【英文标题】:COM method call fails in C#, VB.NET, but works in Python 【发布时间】:2010-10-07 18:55:11 【问题描述】:

我在尝试使用的 COM 库时遇到问题。当我调用特定方法并将其传递给null 时,我得到一个 ArgumentException。这发生在我的 C# 项目和 VB.NET 项目(我使用 Nothing 调用该方法)中,我在 Visual Studio 2008 的“COM”列表中添加了库引用。当我在 Python 中调用相同的方法时,传入None,该方法按预期工作,没有错误。我的理解是 Python 通过 DCOM 与 COM 库交互(我只有最模糊的概念),而当我在 C#/VB.NET 项目中引用它时,我可能会直接使用 COM 库。会不会发生什么事情会导致我传递的参数在它到达 COM 库之前搞砸了?我不确定这里发生了什么。我最近将 COM 库更新到了较新的版本,所以我想知道我是否在某个地方遇到了版本冲突,从而导致了异常。我从我的 C# 和 VB.NET 项目中删除了对 COM 库的所有引用,删除了所有 binobj 目录,并重新添加了引用。这确实导致显示在 obj 中的 Interop.MyCOMLibrary.dll 文件具有今天的日期,而不是我之前看到的旧日期。

我拥有的关于 COM 库的唯一文档描述该方法如下:

Public Function AddItem( _
   ByVal ItemData As Variant _
) As Object

我现在正在尝试搜索有关Variant 参数的问题。

编辑:所以虽然Type.Missing 和其他解决方案可以让我顺利通过该方法调用,但尝试从该方法读取返回项目的某些字符串属性会导致:

System.Runtime.InteropServices.COMException:项目不存在。

这是另一个在 Python 中工作但在 C# 中引发异常的示例,所以我猜测更多 DCOM 与 COM 的怪异之处。或者这可能是一个线程问题,因为我正在使用 MSTest 进行测试。

【问题讨论】:

【参考方案1】:

是的,null 不太可能是正确的。有几个变体表示“无数据”,例如 VT_EMPTY、VT_ERROR、VT_NULL。首先传递 Type.Missing。

【讨论】:

看起来Type.Missing 有效!我发布了一个关于如何传递 new object() 的答案,但我猜 Type.Missing 在这里更可取,因为它听起来更接近我想要传递的原始 null【参考方案2】:

您是否尝试过使用 Reflection.Missing 而不是 Nothing/null?

【讨论】:

我刚才试了AddItem(default(System.Reflection.Missing)),得到了和往常一样的ArgumentException。我不确定你打算如何使用Missing,所以我只是尝试了default() @Sarah 试试System.Reflection.Missing.Value @Sarah, @Henk:是的,就像他说的,使用 Missing.Value。 看起来可行! Hans 建议 Type.Missing 可行,我发现 new object() 可行。我认为Type.Missing 听起来更可取,因为除非必要,否则我尽量不使用Reflection 的东西。不过,我不知道这两者是否真的有任何区别。 @Sarah:System.Type.Missing 实际上在 Type 的静态构造函数中设置为等于 System.Reflection.Missing.Value。我认为 Type.Missing 是在 .NET 1.0 之后添加的,但我不确定。我知道 System.Reflection.Missing.Value 是我过去必须为所有可选参数执行此操作的方式。 Type.Missing 更短,所以我现在就使用它。【参考方案3】:

我在this article 中读到关于从 VB 到 VB.NET 的信息,它说在 .NET 中使用 object,因为 Variant 不存在。我之前尝试过传递default(object),但没有成功,但我尝试将new object() 作为参数传递并且有效——没有抛出异常!我不明白为什么在应该是可选参数时必须传递对象的实例。为什么null 不能以某种方式翻译成new object()

在 *** 上输入这个问题是我在纠结了两天后得到这个答案的原因,因为我不得不从文档中复制/粘贴确切的方法描述。那时我注意到Variant 而不是Object 的参数。 :)

【讨论】:

【参考方案4】:

您可以尝试使用System.DBNull.Value 作为参数吗?

我今天不得不以艰难的方式找到这一点。 在尝试了答案中的所有建议后,其中一些导致引发 Argument Exception,而在其他情况下,对 AddItem 的调用静默返回 null

我所做的是在 Visual Studio 解决方案中创建一个新的 VB 项目,其中包含一个带有单个 Shared 方法的单个类,该方法为我调用,打算将来自 VB 的 Null 作为参数传递。编译器抱怨 Null 不再使用,并建议改用System.DBNull.Value。这成功了,正如我后来注意到的那样,System.DBNull.Value 也在 C# 项目中工作。

【讨论】:

以上是关于COM 方法调用在 C#、VB.NET 中失败,但在 Python 中有效的主要内容,如果未能解决你的问题,请参考以下文章

C# 等效于 VB.NET 接口实现

VB.NET中的类和模块

从 Java 调用 VB.NET 函数的最佳方法是啥?

如何在 Visual C# 中使用设置

当两个方法同名但参数不同时如何在VB.Net中实现一个接口

我们可以在最初使用 C# 安装的 Visual Studio Express 中运行 VB.Net 吗?