C#COM服务器从GetIDsOfNames返回E#U指针
我试图在C#中创建一个COM服务器,以公开一个OLE自动化对象。我想手动实现IDispatch接口,因为我需要对成员进行一些动态查找。当我调用我的自定义C#COM服务器从GetIDsOfNames返回E#U指针,c#,comobject,idispatch,ole-automation,C#,Comobject,Idispatch,Ole Automation,我试图在C#中创建一个COM服务器,以公开一个OLE自动化对象。我想手动实现IDispatch接口,因为我需要对成员进行一些动态查找。当我调用我的自定义GetIDsOfNames时,C方法运行,然后客户端使用E_指针出错。但是让我们从头开始 经过几个小时的阅读和大量的尝试和错误,我已经设法拼凑出一些我认为应该有用的东西。我有一个非常简单的界面 [Guid("7B95C174-9320-4400-88AB-6960B019CEDE")] [ComVisible(true)] public inte
GetIDsOfNames
时,C方法运行,然后客户端使用E_指针出错。但是让我们从头开始
经过几个小时的阅读和大量的尝试和错误,我已经设法拼凑出一些我认为应该有用的东西。我有一个非常简单的界面
[Guid("7B95C174-9320-4400-88AB-6960B019CEDE")]
[ComVisible(true)]
public interface ISimpleObject {
EchoObject testNest();
}
它可以返回另一个COM对象。第一个COM对象使用默认的C#IDispatch实现,工作正常。EchoObject是一个带有自定义IDispatch实现的对象,因为它不是C#SDK的一部分。让我们看看我是如何定义它的
[ComImport]
[Guid("00020400-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDispatch {
int GetTypeInfoCount(out uint pctinfo);
int GetTypeInfo(uint iTInfo, int lcid, out IntPtr info);
int GetIDsOfNames(
ref Guid iid,
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 2)] string[] names,
int cNames,
int lcid,
[Out][MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I4, SizeParamIndex = 2)] int[] rgDispId);
int Invoke(
int dispId,
ref Guid riid,
int lcid,
System.Runtime.InteropServices.ComTypes.INVOKEKIND wFlags,
ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams,
[Out][MarshalAs(UnmanagedType.LPArray)] object[] result,
IntPtr pExcepInfo,
IntPtr puArgErr);
}
我在IEchoObject接口的定义中使用定义的IDispatch接口
[Guid("D3E9B530-DFD5-4B54-88B9-4FBC8B0926E2")]
[ComVisible(true)]
public interface IEchoObject: IDispatch {
string testint();
}
然后,该接口的实现必须实现ICustomQueryInterface,以允许IDispatch转换进行
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IDispatch))]
[Guid("F625A833-3B4E-455D-90A9-89B1953147CD"), ComVisible(true)]
public class EchoObject : ReferenceCountedObject, IEchoObject, ICustomQueryInterface {
public CustomQueryInterfaceResult GetInterface(ref Guid iid, out IntPtr ppv) {
Console.WriteLine("Are we a: " + iid + "?");
ppv = IntPtr.Zero;
if (typeof(IDispatch).GUID == iid)
{
Console.WriteLine("Yes");
ppv = Marshal.GetComInterfaceForObject(this, typeof(IDispatch), CustomQueryInterfaceMode.Ignore);
return CustomQueryInterfaceResult.Handled;
}
return CustomQueryInterfaceResult.NotHandled;
}
public int GetIDsOfNames(
ref Guid iid,
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 2)] string[] names,
int cNames,
int lcid,
[Out][MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I4, SizeParamIndex = 2)] int[] rgDispId
) {
bool unknown = false;
if(cNames == 1) {
Console.WriteLine("Getting id of " + names[0]);
if (names[0] == "testman") {
Console.WriteLine("Member found");
rgDispId[0] = 1;
} else {
rgDispId[0] = -1;
}
}
return unknown ? HRESULT.DISP_E_UNKNOWNNAME : HRESULT.S_OK;
}
}
我当然已经实现了IDispatch的其他方法,但我不认为它们对我遇到的问题很重要。请注意,GetIDsOfNames打印到控制台
我可以很好地创建初始的SimpleObject
。我还可以对其调用testNest
方法,并获取EchoObject
实例。但是,当在该EchoObject
上查找testman
方法的ID时,客户端从win32返回一个E_指针(无效指针),而不是结果
我已经用Excel、VBScript和一个定制的C++ COM客户机测试了它。都得到一个无效指针错误,C++客户端显示它来自代码> GETDISSONDISS/<代码>。奇怪的是,C语言方法运行时,它愉快地将该行打印到控制台,然后返回,然后C++ COM客户端会得到一个错误。
如果禁用所有自定义IDispatch,而使用默认的C#实现(调用testint方法而不是testman),则效果很好。我怀疑我的编组可能在某个地方出错,但我已经盯着它看了好几个小时,看不出问题所在
编辑:我做了另一个测试。如果我将GetIDsOfNames的返回类型从int更改为void,它将起作用。那里发生了什么事?根据示例,返回类型是HRESULT(一个32位带符号的int),但是当我返回时,我会得到一个错误。@HansPassant通常你可能是对的,但是对于我的用例,我不知道编译时有哪些方法可用,所以我需要在运行时查找它们。这在自动IDispatch实现中是不可能的。IReflect接口也不适用,因为我仍然需要知道启动时可以提供的所有方法。@HansPassant我不明白我自己的要求怎么可能是错误的。我正在COM和一些外部系统之间实现一个代理。我不知道这个外部系统的对象有哪些方法,但是如果我有一个名字,我可以出去问它是否有那个特定的成员。我不知道有什么方法可以在不亲自实现IDispatch的情况下实现这一点。默认的IDispatch实现只回答编译时已知的成员(它们必须在接口中定义)。@HansPassant通常您可能是对的,但对于我的用例,我不知道编译时有哪些方法可用,所以我需要在运行时查找它们。这在自动IDispatch实现中是不可能的。IReflect接口也不适用,因为我仍然需要知道启动时可以提供的所有方法。@HansPassant我不明白我自己的要求怎么可能是错误的。我正在COM和一些外部系统之间实现一个代理。我不知道这个外部系统的对象有哪些方法,但是如果我有一个名字,我可以出去问它是否有那个特定的成员。我不知道有什么方法可以在不亲自实现IDispatch的情况下实现这一点。默认的IDispatch实现只对编译时已知的成员进行应答(它们必须在接口中定义)。