【问题标题】:Packaging IDispatch Invoke with Parameters in C# (with DISPPARAMS)在 C# 中使用参数打包 IDispatch 调用(使用 DISPARAMS)
【发布时间】:2011-03-24 02:40:46
【问题描述】:

我正在使用 Invoke 对支持 IDispatch 的旧 COM 对象进行后期绑定。这似乎是必要的,因为 .NET 的 Type.GetMethod Type.InvokeMember 似乎不适用于这些对象。

以下代码适用于从对象获取属性,调用者将属性名称作为字符串传递,用于通过后期绑定获取属性值。该类在其构造函数中获取一个对象,并将 this.idisp(和 this.lcid)设置为指向该对象的接口指针(欢迎批评!)

public object InvokeGet(string propertyName)
{
    int id = GetDispID(propertyName);
    IntPtr[] pArgErr = default(IntPtr[]);
    object pVarResult;
    System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams = default(System.Runtime.InteropServices.ComTypes.DISPPARAMS);
    System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo = default(System.Runtime.InteropServices.ComTypes.EXCEPINFO);

    Guid guid = new Guid();
    int result = this.idisp.Invoke(id, ref guid, (uint)this.lcid,
                 (ushort)System.Runtime.InteropServices.ComTypes.INVOKEKIND.INVOKE_PROPERTYGET,
                 ref pDispParams, out pVarResult, ref pExcepInfo, pArgErr);

    if (result != 0)
    {
        throw new ArgumentException(string.Format("Error invoking property: {0}.  COM error code is {1}", propertyName, result));
    }

    return pVarResult;
}

我现在正在尝试编写 setter 等价物,即

public void InvokeSet(string propertyName, object newValue)

但是我不确定如何使用 C# 打包 Dispatch 参数。

即如何设置结构:

System.Runtime.InteropServices.ComTypes.DISPPARAMS 

我知道我需要创建一个从托管对象到编组的非托管变体。有什么建议吗?

【问题讨论】:

    标签: c# com automation marshalling idispatch


    【解决方案1】:

    我知道聚会很晚,但我找到了答案。

    // Create the DISPPARAMS struct
    var pDispParams= default(System.Runtime.InteropServices.ComTypes.DISPPARAMS);
    // Set the number of unnamed parameters
    pDispParams.cArgs = 1;
    
    // Marshal a value to a variant
    int value = 10;
    IntPtr pVariant = Marshal.AllocCoTaskMem(16); // Default VARIANT size
    Marshal.GetNativeVariantForObject(value, pVariant);
    
    // Set the unnamed parameter arguments
    pDispParams.rgvarg = pVariant;
    
    // Call the IDispatch.Invoke
    int result = this.idisp.Invoke(id, ref guid, (uint)this.lcid, 
        (ushort)System.Runtime.InteropServices.ComTypes.INVOKEKIND.INVOKE_PROPERTYGET,
        ref pDispParams, out pVarResult, ref pExcepInfo, pArgErr);
    

    我无法弄清楚如何在 C# 中编组变体。我找到了this article,它基本上回答了我所有未解决的问题,也回答了你的问题。

    希望这仍然对某人有所帮助。

    【讨论】:

    • 将 Args 与 INVOKE_PROPERTYGET 一起使用?传递 Args 时不应该只使用 PUT、PUTREF 或 METHOD 标志吗?
    猜你喜欢
    • 2023-01-18
    • 2020-07-24
    • 2010-10-31
    • 2023-03-24
    • 2014-08-30
    • 1970-01-01
    • 2011-08-06
    • 2016-07-25
    • 1970-01-01
    相关资源
    最近更新 更多