【问题标题】:Calling a member of IDispatch COM interface from C#从 C# 调用 IDispatch COM 接口的成员
【发布时间】:2011-12-25 11:44:58
【问题描述】:

我想从实现 C# 中的 IDispatch 接口的 COM 对象调用 GetIdsOfNames 函数。我编写了以下代码,但由于 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);

谢谢,

理查德

【问题讨论】:

    标签: c# com


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-03-15
        • 2021-07-10
        • 1970-01-01
        • 1970-01-01
        • 2010-10-31
        • 2021-06-12
        • 2014-07-02
        相关资源
        最近更新 更多