2011-11-09 77 views
5

我想從實現IDispatch接口的COM對象中調用GetIdsOfNames函數。我寫了下面的代碼,但是它失敗了,並且DISP_E_UNKNOWNNAME。這是做這件事的正確方法嗎?調用C#中IDispatch COM接口的成員#

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); 

感謝,

理查德

回答

4

,你不行,因爲InvokeMember內部使用的GetIDsOfNames,而這一次只檢查實際的方法,而不是在IDispatch的第6。換句話說,不能使用IDispatch的方法Invoke調用GetIDsOfNames。這就是COM的工作原理。

21

是的,不起作用,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); 
    } 
} 
+0

謝謝。這真的很有幫助。 –