使用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-设置属性不工作
怎么了?
您应该这样更改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;
}
}