使用ICustomQueryInterface实现IDispatch.Set属性-不起作用

本文关键字:属性 不起作用 Set IDispatch ICustomQueryInterface 实现 使用 | 更新日期: 2023-09-27 18:27:10

演示示例:

Echo.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);
    }
}

echo.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-设置属性不工作

怎么了?

使用ICustomQueryInterface实现IDispatch.Set属性-不起作用

您应该这样更改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;
    }
}