2011-11-09 4 views
5

Quería llamar a la función GetIdsOfNames desde un objeto COM que implementa la interfaz IDispatch en C#. He escrito el siguiente código pero falla con DISP_E_UNKNOWNNAME. ¿Es este el enfoque correcto para hacer esto?Llamar a un miembro de la interfaz COM de IDispatch desde C#

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

Gracias,

Richard

Respuesta

4

No, no puedes, porque InvokeMember utiliza internamente GetIDsOfNames, y éste sólo comprueba los métodos actuales, no la primera 6 en IDispatch. O, en otras palabras, GetIDsOfNames no se puede invocar con el método de IDispatch Invoke. Así es como funciona COM.

21

Sí, no funciona, el RCW no expone los métodos IDispatch. Debe obtener la referencia de la interfaz IDispatch explícitamente. Esto funcionó bien:

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

gracias. Eso es realmente muy útil. –

Cuestiones relacionadas