代码之家  ›  专栏  ›  技术社区  ›  Mister Cook

将IDispatch调用与c中的参数打包(使用DispParams)

  •  3
  • Mister Cook  · 技术社区  · 16 年前

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

    以下代码可以很好地从对象获取属性,调用者将属性名作为字符串传入,以获取后期绑定的属性值。类在其构造函数中接受一个对象,并将此.idisp(和此.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打包调度参数。

    即如何设置结构:

    System.Runtime.InteropServices.ComTypes.DISPPARAMS 
    

    我知道我需要从托管对象创建一个非托管变量来封送。有什么建议吗?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Carson    7 年前

    我知道参加聚会很晚,但我为你找到了答案。

    // 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 它基本上回答了我和你所有的悬而未决的问题。

    希望这能帮助别人。