尝试使用c#调用COM对象上的方法时出现异常 .

只有当我尝试在不使用tlbimp.exe生成的COM运行时可调用包装器(RCW)互操作程序集的情况下调用该方法时,才会发生这种情况 .

当严格使用COM互操作程序集时,一切都很完美 .

我不想使用COM互操作程序集的原因是因为目标机器上的CLSID和ProgID可能与创建互操作程序集时不同,但方法名称,定义和结构是相同的 .

但是,在此测试中,COM服务器使用与运行时可调用包装器(RCW)中定义的相同的CLSID和ProgID进行注册,该运行时可直接从正在运行的COM服务器程序集生成 .

在Windows 7 SP1 64位上运行 .
C COM服务器是32位
C#程序集使用"Any CPU"构建,目标是.NET Framework 4

C COM服务器IDL代码段:

[
object,
uuid(MyComObjectInterfaceGuid),
dual,
helpstring("MyComObject Interface"),
pointer_default(unique)
]
interface IMyComObject : IDispatch
{
    #import "MyCustomStruct.h"
    [id(110), helpstring("Method110")] HRESULT Method110([out] MY_CUSTOM_STRUCT *pMyCustomStruct);
}

[
uuid(MyComObjectGuid),
helpstring("MyComObject")
]
coclass MyComObject
{
    [default] interface IMyComObject;
};

MyCustomStruct.h:

#define MyCustomType2 MyCustomType;
#define long unsigned MyCustomType2;

typedef struct MY_CUSTOM_STRUCT
{
    bool            property1;
    MyCustomType    property2;
    wchar_t         property3[42];
    int             property4;
} MY_CUSTOM_STRUCT;

注册COM服务器DLL时,rgs文件插入ProgId注册表值 .

运行时可调用包装器生成以下结构:

public struct MY_CUSTOM_STRUCT
{
    public byte property1;
    public MyCustomType property2;
    public ushort[] property3;
    public int property4;
}

public struct MyCustomType
{
    public uint @value;
}

适用的C#代码段:

using MyComObjectInteropNamespace;

MyComObject myComObject = new MyComObject();

MY_CUSTOM_STRUCT myCustomStruct = new MY_CUSTOM_STRUCT();
myComObject.Method110(out myCustomStruct);

// myCustomStruct contains the expected values

引发异常的C#代码段:

using MyComObjectInteropNamespace;

Type myComObjectType = Type.GetTypeFromProgID("Company.Product.MyComObject", true);
object myComObject = Activator.CreateInstance(myComObjectType);

MY_CUSTOM_STRUCT myCustomStruct = new MY_CUSTOM_STRUCT();
object[] args = { myCustomStruct };

ParameterModifier parameterModifier = new ParameterModifier(1);
parameterModifier[0] = true;
ParameterModifier[] parameterModifiers = { parameterModifier };

myComObjectType.InvokeMember( // exception is thrown here
    "Method110",
    BindingFlags.InvokeMethod,
    null,
    myComObject,
    args,
    parameterModifiers,
    null,
    null);

// code does not get this far
myCustomStruct = (MY_CUSTOM_STRUCT)args[0];

例外:

System.ArgumentException occurred
  HResult=-2147024809
  Message=Value does not fall within the expected range.
  Source=mscorlib
  StackTrace:
       at System.RuntimeType.InvokeDispMethod(String name, BindingFlags invokeAttr, Object target, Object[] args, Boolean[] byrefModifiers, Int32 culture, String[] namedParameters)
       at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
  InnerException:

C#代码片段也会抛出相同的异常:

using MyComObjectInteropNamespace;

Type myComObjectType = Type.GetTypeFromProgID("Company.Product.MyComObject", true);
object myComObject = Activator.CreateInstance(myComObjectType);

object[] args = { new UnknownWrapper(null) };

ParameterModifier parameterModifier = new ParameterModifier(1);
parameterModifier[0] = true;
ParameterModifier[] parameterModifiers = { parameterModifier };

myComObjectType.InvokeMember( // exception is thrown here
    "Method110",
    BindingFlags.InvokeMethod,
    null,
    myComObject,
    args,
    parameterModifiers,
    null,
    null);

// code does not get this far
MY_CUSTOM_STRUCT myCustomStruct = (MY_CUSTOM_STRUCT)args[0];

C#代码段也会引发异常:

dynamic myComObject = Activator.CreateInstance(Type.GetTypeFromProgID("Company.Product.MyComObject", true));

MY_CUSTOM_STRUCT myCustomStruct = new MY_CUSTOM_STRUCT();
myComObject.Method110(out myCustomStruct); // exception is thrown here

例外:

System.ArgumentException occurred
  HResult=-2147024809
  Message=Value does not fall within the expected range.
  Source=mscorlib
  StackTrace:
       at System.Runtime.InteropServices.Marshal.GetNativeVariantForObject(Object obj, IntPtr pDstNativeVariant)
       at System.Dynamic.UnsafeMethods.InitVariantForObject(Object obj, Variant& variant)
  InnerException: null

我也在MSDN论坛上发布了here