c# - 使用 ICustomQueryInterface 实现 IDispatch。设置属性 - 不工作

标签 c# com

演示示例:

回声.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;

namespace EchoProject
{
    [ComVisible(true)]
    [ProgId("EchoProject.Echo")]
    [ClassInterface(ClassInterfaceType.None)]
    public class Echo : IDispatch, ICustomQueryInterface
    {
        private int lastDispId = 0;
        private Dictionary<int, string> dispIdNameMap = new Dictionary<int, string>();

        public CustomQueryInterfaceResult GetInterface(ref Guid iid, out IntPtr ppv)
        {
            ppv = IntPtr.Zero;
            if (typeof(IDispatch).GUID == iid)
            {
                ppv = Marshal.GetComInterfaceForObject(this, typeof(IDispatch), CustomQueryInterfaceMode.Ignore);
                return CustomQueryInterfaceResult.Handled;
            }
            return CustomQueryInterfaceResult.NotHandled;
        }

        public void GetTypeInfoCount(out uint pctinfo)
        {
            pctinfo = 0;
        }

        public void GetTypeInfo(uint iTInfo, int lcid, out IntPtr info)
        {
            info = IntPtr.Zero;
        }

        public void GetIDsOfNames(ref Guid iid, string[] names, int cNames, int lcid, int[] rgDispId)
        {
            for (int i = 0; i < cNames; i++ )
            {
                KeyValuePair<int, string> pair = dispIdNameMap.SingleOrDefault(p => p.Value == names[i]);
                if (pair.Key == 0)
                {
                    dispIdNameMap.Add(++lastDispId, names[i]);
                    rgDispId[i] = lastDispId;
                }
                else
                {
                    rgDispId[i] = pair.Key;
                }
            }
        }

        public void Invoke(int dispId, ref Guid riid, int lcid, System.Runtime.InteropServices.ComTypes.INVOKEKIND wFlags, ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams, out object result, IntPtr pExcepInfo, IntPtr puArgErr)
        {
            string name;
            dispIdNameMap.TryGetValue(dispId, out name);
            result = name;
        }
    }
}

IDispatch.cs:

using System;
using System.Runtime.InteropServices;

namespace EchoProject
{
    [ComImport]
    [Guid("00020400-0000-0000-C000-000000000046")]
    [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IDispatch
    {
        void GetTypeInfoCount(out uint pctinfo);

        void GetTypeInfo(uint iTInfo, int lcid, out IntPtr info);

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

        void Invoke(
            int dispId,
            ref Guid riid,
            int lcid,
            System.Runtime.InteropServices.ComTypes.INVOKEKIND wFlags,
            ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams,
            out object result,
            IntPtr pExcepInfo,
            IntPtr puArgErr);
    }
}

回声.js:

var echo = new ActiveXObject("EchoProject.Echo");
WScript.Echo("Begin debug");
WScript.Echo(echo.foo()); //foo
WScript.Echo(echo.bar); //bar
echo.baz = 1; //error

调用方法“foo”- 工作。 获取属性“bar” - 工作。 设置属性“baz”- 不工作!!!

我尝试使用 .NET 框架版本:4.5; 4.5.1; 4.5.2 - 设置属性不起作用

有什么问题?

最佳答案

您应该像这样更改 Invoke 定义:

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

并像这样使用它:

public void Invoke(int dispId, ref Guid riid, int lcid, System.Runtime.InteropServices.ComTypes.INVOKEKIND wFlags, ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams, out object result, IntPtr pExcepInfo, IntPtr puArgErr)
{
    string name;
    dispIdNameMap.TryGetValue(dispId, out name);
    if (result != null)
    {
        result[0] = name;
    }
}

关于c# - 使用 ICustomQueryInterface 实现 IDispatch。设置属性 - 不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26459041/

相关文章:

c# - 使用什么对象类型/实例进行同步

wpf - 在 WebBrowser 控件上显示装饰器

python - Excel python COM 对象的文档?

c# - 字符串格式一位小数

c# - LINQ multiple join IQueryable 修改结果选择器表达式

java - Java SecretKeySpec 的 C# 等价物是什么

wcf - 使用 COM 优于 WCF 的优势

c# - 学习单声道源代码

windows - Spectre/Meltdown 补丁导致 COM 方法返回 E_ACCESSDENIED

c++ - 在服务启动期间调用 CoCreateInstance