从C#调用IDispatch COM接口的成员

我想从COM对象调用GetIdsOfNames函数,该对象在c#中实现IDispatch接口。 我编写了以下代码,但它失败了DISP_E_UNKNOWNNAME。 这是正确的做法吗?

Object so = Activator.CreateInstance(Type.GetTypeFromProgID("ProgID")); Object[] args = new Object[5]; string[] rgsNames = new string[1]; rgsNames[0] = "PrintNormal"; uint LOCALE_SYSTEM_DEFAULT = 0x0800; uint lcid = LOCALE_SYSTEM_DEFAULT; int cNames = 1; int[] rgDispId = new int[1]; args[0] = IntPtr.Zero; args[1] = rgsNames; args[2] = cNames; args[3] = lcid; args[4] = rgDispId; Object result = so.GetType().InvokeMember("GetIDsOfNames", BindingFlags.InvokeMethod, null, so, args); 

谢谢,

理查德

不,你不能,因为InvokeMember内部使用GetIDsOfNames,而这只检查实际方法,而不是IDispatch中的前6个。 或者换句话说,使用IDispatch的方法Invoke不能调用GetIDsOfNames。 这就是COM的工作原理。

是的,不起作用,RCW不公开IDispatch方法。 您必须显式获取IDispatch接口引用。 这很好用:

 using System; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; class Program { static void Main() { Object so = Activator.CreateInstance(Type.GetTypeFromProgID("SAPI.SpVoice")); string[] rgsNames = new string[1]; int[] rgDispId = new int[1]; rgsNames[0] = "Speak"; IDispatch disp = (IDispatch)so; Guid dummy = Guid.Empty; disp.GetIDsOfNames(ref dummy, rgsNames, 1, 0x800, rgDispId); Console.WriteLine(rgDispId[0]); } [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00020400-0000-0000-C000-000000000046")] private interface IDispatch { int GetTypeInfoCount(); [return: MarshalAs(UnmanagedType.Interface)] ITypeInfo GetTypeInfo([In, MarshalAs(UnmanagedType.U4)] int iTInfo, [In, MarshalAs(UnmanagedType.U4)] int lcid); void GetIDsOfNames([In] ref Guid riid, [In, MarshalAs(UnmanagedType.LPArray)] string[] rgszNames, [In, MarshalAs(UnmanagedType.U4)] int cNames, [In, MarshalAs(UnmanagedType.U4)] int lcid, [Out, MarshalAs(UnmanagedType.LPArray)] int[] rgDispId); } }