使用C#中的参数打包IDispatch调用(使用DISPPARAMS) [英] Packaging IDispatch Invoke with Parameters in C# (with DISPPARAMS)

查看:564
本文介绍了使用C#中的参数打包IDispatch调用(使用DISPPARAMS)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using Invoke for late binding on a legacy COM objects that supports IDispatch. This seems necessary as .NET's Type.GetMethod Type.InvokeMember do not seem to work on these objects.

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

The following code works fine for getting a property from an object, the caller passes in the property name as a string for getting the property value with late binding. The class takes an object in its constructor and sets up this.idisp (and this.lcid) as an interface pointer to the object (Critiques welcome!)

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,即

I'm now trying to write the setter equivalent, i.e.

public void InvokeSet(string propertyName, object newValue)

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

however I am not sure how to package up the Dispatch paramaters with C#.

即如何设置结构:

System.Runtime.InteropServices.ComTypes.DISPPARAMS 

我知道我需要从托管对象创建非托管变体以进行封送.有什么建议怎么做吗?

I understand I need to create an unmanaged variant from the managed object to marshal. Any suggestions how to do this?

推荐答案

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

Very late to the party, I know, but I found an answer for you.

// 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#中编组变体.我发现这篇文章基本上回答了我所有的悬而未决的问题,也回答了您的所有问题,也是.

I had trouble figuring out how to marshal the variant in C#. I found this article which essentially answered all of my outstanding questions, and yours, too.

希望这仍然可以对某人有所帮助.

Hopefully this still helps someone.

这篇关于使用C#中的参数打包IDispatch调用(使用DISPPARAMS)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆