尝试使用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: