如何为COM使用创建propput IDL method.NET接口

如何为COM使用创建propput IDL method.NET接口,.net,com-interop,idl,variant,.net,Com Interop,Idl,Variant,我在Excel/VBA中使用.NET/ComVisible程序集时遇到问题。我在.NET中将几个参数定义为“对象”,因此它们将在VBA中转换为变量,因为VBA中的可选参数需要使用变量类型 问题是,当我尝试在Excel/VBA中使用该对象时,会出现“运行时错误'424':需要对象”。我认为我在C#界面中缺少了一些属性,这些属性将添加一个“propput”方法,而不是“propputref”方法,该方法将允许变量中的值,但我在互联网上找不到类似问题的答案。我看到System.Reflection.B

我在Excel/VBA中使用.NET/ComVisible程序集时遇到问题。我在.NET中将几个参数定义为“对象”,因此它们将在VBA中转换为变量,因为VBA中的可选参数需要使用变量类型

问题是,当我尝试在Excel/VBA中使用该对象时,会出现“运行时错误'424':需要对象”。我认为我在C#界面中缺少了一些属性,这些属性将添加一个“propput”方法,而不是“propputref”方法,该方法将允许变量中的值,但我在互联网上找不到类似问题的答案。我看到System.Reflection.BindingFlags,但这似乎只适用于编译时和运行时代码,而不适用于接口定义

底层数据类型是double,我需要它为null或通过COM/VBA为double。我对字符串参数没有任何问题,只有variant/double

这里是C#接口:

[ComVisible(true)]
[Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface ISampleParameters
{
    object GrossObservedValue { get; set; }
    string TableName { get; set; }
    // Rest of parameters removed for simplicity
}
这是C#对象:

以下是VBA的用法:

Dim Parameters As New SampleParameters
Parameters.GrossObservedValue = 1.23
' Causes: Run-time error '424': Object required
以下是OleView中的类型库IDL:

[
  odl,
  uuid(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX),
  version(1.0),
  dual,
  oleautomation,
  custom(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, TempNamespace.ISampleParameters)    
]
interface ISampleParameters : IDispatch {
    [id(0x60020000), propget]
    HRESULT GrossObservedValue([out, retval] VARIANT* pRetVal);
    [id(0x60020000), propputref]
    HRESULT GrossObservedValue([in] VARIANT pRetVal);
    [id(0x60020001), propget]
    HRESULT TableName([out, retval] BSTR* pRetVal);
    [id(0x60020001), propput]
    HRESULT TableName([in] BSTR pRetVal);
};

似乎唯一的解决方案是手动生成IDL,然后将其导入到.NET中,如中所示。这是唯一的解决办法吗?关于在托管代码中使用COM的要点也很好,但没有涉及在.NET/C#中定义接口。

此错误通常是由于COM组件注册不正确造成的


您对组件使用了什么注册方法?

我使用“regasm/tlb”进行注册。但是,由于程序集输出和生成的TLB在GrossObservedValue setter中具有变量参数,因此在GrossObservedValue setter中具有“propputref”而不是“propput”,我认为这很可能是编译时与注册无关。可以使用propputref,因为传递16字节的变量是次优的。澄清:从VB访问属性TableName是否正常工作?要检查您的假设是否正确,您可以取消注册TLB,从正确的IDL构建您自己的TLB并手动注册。如果这可以解决您的问题,那么您可以进一步使用此TLB,将其与您的程序集一起传递,例如作为嵌入式资源。我还对如何解决此问题感兴趣;我觉得这是类型库生成的一个问题,它在.NET4.0(C#和VB.NET)中都存在。这使得执行基于COM的系统的逐步转换非常困难,因为类型库相等是必须的。
[
  odl,
  uuid(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX),
  version(1.0),
  dual,
  oleautomation,
  custom(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, TempNamespace.ISampleParameters)    
]
interface ISampleParameters : IDispatch {
    [id(0x60020000), propget]
    HRESULT GrossObservedValue([out, retval] VARIANT* pRetVal);
    [id(0x60020000), propputref]
    HRESULT GrossObservedValue([in] VARIANT pRetVal);
    [id(0x60020001), propget]
    HRESULT TableName([out, retval] BSTR* pRetVal);
    [id(0x60020001), propput]
    HRESULT TableName([in] BSTR pRetVal);
};