Упаковка IDispatch Invoke с параметрами в C # (с DISPPARAMS) - PullRequest
3 голосов
/ 02 августа 2010

Я использую Invoke для позднего связывания с устаревшими COM-объектами, которые поддерживают IDispatch. Это кажется необходимым, так как .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;
}

Я сейчас пытаюсь написать сеттерный эквивалент, т.е.

public void InvokeSet(string propertyName, object newValue)

однако я не уверен, как упаковать параметры Dispatch с помощью C #.

т.е.. как настроить структуру:

System.Runtime.InteropServices.ComTypes.DISPPARAMS 

Я понимаю, что мне нужно создать неуправляемый вариант от управляемого объекта до маршала. Любые предложения, как это сделать?

1 Ответ

1 голос
/ 09 октября 2018

Очень поздно на вечеринку, я знаю, но я нашел для вас ответ.

// 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 #. Я нашел эту статью , которая, по сути, ответила на все мои нерешенные вопросы, и ваши тоже.

Надеюсь, это кому-то еще поможет.

...