public static int InvokePropertyGet(this IDispatch dispatch, int dispid, out object value)
        {
            int hr = NativeMethods.S_OK;

            value = null;

            var  guid       = Guid.Empty;
            var  lcid       = NativeMethods.LOCALE_SYSTEM_DEFAULT;
            var  flags      = System.Runtime.InteropServices.ComTypes.INVOKEKIND.INVOKE_PROPERTYGET;
            var  dp         = default(System.Runtime.InteropServices.ComTypes.DISPPARAMS);
            var  pExcepInfo = default(System.Runtime.InteropServices.ComTypes.EXCEPINFO);
            uint pArgErr    = 0;

            Variant variant = default(Variant);

            try
            {
                hr = dispatch.Invoke(
                    dispid,
                    ref guid,
                    lcid,
                    flags,
                    ref dp,
                    out variant,
                    ref pExcepInfo,
                    out pArgErr
                    );

                if (MarshalEx.Succeeded(hr))
                {
                    try
                    {
                        switch (variant.VariantType)
                        {
                        case VarEnum.VT_PTR:
                            GlobalExceptionHandler.HandleException();
                            break;

                        case VarEnum.VT_UNKNOWN:
                        case VarEnum.VT_DISPATCH:
                            if (variant.ptr1.Equals(IntPtr.Zero) == false)
                            {
                                value = new ComPtr(variant.ptr1);
                                int count = Marshal.Release(variant.ptr1);
                            }
                            break;

                        case VarEnum.VT_USERDEFINED:
                            value = variant.ToObject();
                            break;

                        default:
                            value = variant.ToObject();
                            break;
                        }
                    }
                    catch (COMException ex)
                    {
                        hr = ex.ErrorCode;
                    }
                }
            }
            catch
            {
                GlobalExceptionHandler.HandleException();
            }
            finally
            {
                variant.Clear();
            }

            return(hr);
        }
        public static int InvokeMethod(this IDispatch dispatch, int dispId, object[] args, out object returnValue)
        {
            int           hr   = NativeMethods.S_OK;
            var           riid = new Guid(NativeMethods.IID_NULL);
            VariantArgPtr va   = new VariantArgPtr(args.Length);

            returnValue = null;

            var dp = new System.Runtime.InteropServices.ComTypes.DISPPARAMS()
            {
                cArgs             = args.Length,
                rgvarg            = va,
                cNamedArgs        = 0,
                rgdispidNamedArgs = IntPtr.Zero
            };

            Array.Reverse(args);

            for (int i = 0; i < args.Length; i++)
            {
                var arg = args[i];

                if (arg is VariantWrapper)
                {
                    Variant variant = new Variant((VariantWrapper)arg);
                    Marshal.StructureToPtr(variant, va[i], false);
                }
                else
                {
                    Marshal.GetNativeVariantForObject(arg, va[i]);
                }
            }

            try
            {
                Variant pVarResult = default(Variant);
                var     pExcepInfo = default(System.Runtime.InteropServices.ComTypes.EXCEPINFO);
                uint    pArgErr    = 0;

                hr = dispatch.Invoke
                     (
                    dispId,
                    ref riid,
                    NativeMethods.LOCALE_SYSTEM_DEFAULT,
                    System.Runtime.InteropServices.ComTypes.INVOKEKIND.INVOKE_FUNC,
                    ref dp,
                    out pVarResult,
                    ref pExcepInfo,
                    out pArgErr
                     );

                if (hr == 0)
                {
                    for (var i = 0; i < args.Length; i++)
                    {
                        var arg = args[i];

                        if (arg is VariantWrapper)
                        {
                            Variant variant = (Variant)Marshal.PtrToStructure(va[i], typeof(Variant));

                            try
                            {
                                switch (variant.VariantType)
                                {
                                case VarEnum.VT_UNKNOWN:
                                case VarEnum.VT_DISPATCH:
                                    args[i] = new ComPtr(variant.ptr1);
                                    if (((ComPtr)returnValue).IsInvalid == false)
                                    {
                                        Marshal.Release(variant.ptr1);
                                    }
                                    break;

                                default:
                                    args[i] = variant.ToObject();
                                    break;
                                }
                            }
                            catch (COMException ex)
                            {
                                hr = ex.ErrorCode;
                            }

                            //VarEnum variantType = variant.VariantType & (VarEnum.VT_NULL | VarEnum.VT_I2 | VarEnum.VT_I4 | VarEnum.VT_R4 | VarEnum.VT_R8 | VarEnum.VT_CY | VarEnum.VT_DATE | VarEnum.VT_BSTR | VarEnum.VT_DISPATCH | VarEnum.VT_ERROR | VarEnum.VT_BOOL | VarEnum.VT_VARIANT | VarEnum.VT_UNKNOWN | VarEnum.VT_DECIMAL | VarEnum.VT_I1 | VarEnum.VT_UI1 | VarEnum.VT_UI2 | VarEnum.VT_UI4 | VarEnum.VT_I8 | VarEnum.VT_UI8 | VarEnum.VT_INT | VarEnum.VT_UINT | VarEnum.VT_VOID | VarEnum.VT_HRESULT | VarEnum.VT_PTR | VarEnum.VT_SAFEARRAY | VarEnum.VT_CARRAY | VarEnum.VT_USERDEFINED | VarEnum.VT_LPSTR | VarEnum.VT_LPWSTR | VarEnum.VT_RECORD | VarEnum.VT_FILETIME | VarEnum.VT_BLOB | VarEnum.VT_STREAM | VarEnum.VT_STORAGE | VarEnum.VT_STREAMED_OBJECT | VarEnum.VT_STORED_OBJECT | VarEnum.VT_BLOB_OBJECT | VarEnum.VT_CF | VarEnum.VT_CLSID | VarEnum.VT_VECTOR | VarEnum.VT_ARRAY);
                            //args[i] = variant.ToObject();
                            //args[i] = Marshal.GetObjectForNativeVariant(variant.variant_part.variant_union._dispatch);
                            //NativeMethods.VariantClear(variant.variant_part.variant_union.pointer_data);
                        }
                    }

                    switch (pVarResult.VariantType)
                    {
                    case VarEnum.VT_UNKNOWN:
                    case VarEnum.VT_DISPATCH:
                        returnValue = new ComPtr(pVarResult.ptr1);
                        if (((ComPtr)returnValue).IsInvalid == false)
                        {
                            Marshal.Release(pVarResult.ptr1);
                        }
                        break;

                    case VarEnum.VT_EMPTY:
                        break;

                    default:
                        returnValue = pVarResult.ToObject();
                        break;
                    }
                }
                else
                {
                    for (var i = 0; i < args.Length; i++)
                    {
                        if (args[i] is VariantWrapper)
                        {
                            args[i] = null;
                        }
                    }
                }

                Array.Reverse(args);
            }
            catch
            {
                GlobalExceptionHandler.HandleException();
            }
            finally
            {
                va.Dispose();
            }

            return(hr);
        }