示例#1
0
        public static void SetProperty(this IDispatchEx dispatchEx, string name, bool ignoreCase, params object[] args)
        {
            if (args.Length < 1)
            {
                throw new ArgumentException("Invalid argument count", "args");
            }

            var dispid = dispatchEx.GetDispIDForName(name, true, ignoreCase);

            using (var argVariantArrayBlock = new CoTaskMemVariantArgsBlock(args))
            {
                using (var namedArgDispidBlock = new CoTaskMemBlock(sizeof(int)))
                {
                    EXCEPINFO excepInfo;
                    Marshal.WriteInt32(namedArgDispidBlock.Addr, SpecialDispIDs.PropertyPut);
                    var dispArgs = new DISPPARAMS {
                        cArgs = args.Length, rgvarg = argVariantArrayBlock.Addr, cNamedArgs = 1, rgdispidNamedArgs = namedArgDispidBlock.Addr
                    };

                    var result = dispatchEx.InvokeEx(dispid, 0, DispatchFlags.PropertyPut | DispatchFlags.PropertyPutRef, ref dispArgs, IntPtr.Zero, out excepInfo);
                    if (result == HResult.DISP_E_MEMBERNOTFOUND)
                    {
                        // VBScript objects can be finicky about property-put dispatch flags

                        result = dispatchEx.InvokeEx(dispid, 0, DispatchFlags.PropertyPut, ref dispArgs, IntPtr.Zero, out excepInfo);
                        if (result == HResult.DISP_E_MEMBERNOTFOUND)
                        {
                            result = dispatchEx.InvokeEx(dispid, 0, DispatchFlags.PropertyPutRef, ref dispArgs, IntPtr.Zero, out excepInfo);
                        }
                    }

                    HResult.Check(result);
                }
            }
        }
示例#2
0
        // This method is intended for use through reflection and should not be used directly
        public static int IDispatchInvoke(
            IntPtr dispatchPointer,
            int memberDispId,
            ComTypes.INVOKEKIND flags,
            ref ComTypes.DISPPARAMS dispParams,
            out Variant result,
            out ExcepInfo excepInfo,
            out uint argErr)
        {
            int hresult = s_iDispatchInvoke(
                dispatchPointer,
                memberDispId,
                flags,
                ref dispParams,
                out result,
                out excepInfo,
                out argErr
                );

            if (hresult == ComHresults.DISP_E_MEMBERNOTFOUND &&
                (flags & ComTypes.INVOKEKIND.INVOKE_FUNC) != 0 &&
                (flags & (ComTypes.INVOKEKIND.INVOKE_PROPERTYPUT | ComTypes.INVOKEKIND.INVOKE_PROPERTYPUTREF)) == 0)
            {
                // Re-invoke with no result argument to accomodate Word
                hresult = _IDispatchInvokeNoResult(
                    dispatchPointer,
                    memberDispId,
                    ComTypes.INVOKEKIND.INVOKE_FUNC,
                    ref dispParams,
                    out result,
                    out excepInfo,
                    out argErr);
            }
            return(hresult);
        }
示例#3
0
        // This method is intended for use through reflection and should not be used directly
        public static unsafe int IDispatchInvoke(
            IntPtr dispatchPointer,
            int memberDispId,
            ComTypes.INVOKEKIND flags,
            ref ComTypes.DISPPARAMS dispParams,
            out Variant result,
            out ExcepInfo excepInfo,
            out uint argErr)
        {
            Guid IID_NULL = default;

            fixed(ComTypes.DISPPARAMS *pDispParams = &dispParams)
            fixed(Variant * pResult      = &result)
            fixed(ExcepInfo * pExcepInfo = &excepInfo)
            fixed(uint *pArgErr          = &argErr)
            {
                var pfnIDispatchInvoke = (delegate * stdcall <IntPtr, int, Guid *, int, ushort, ComTypes.DISPPARAMS *, Variant *, ExcepInfo *, uint *, int>)
                                             (*(*(void ***)dispatchPointer + 6 /* IDispatch.Invoke slot */));

                int hresult = pfnIDispatchInvoke(dispatchPointer,
                                                 memberDispId, &IID_NULL, 0, (ushort)flags, pDispParams, pResult, pExcepInfo, pArgErr);

                if (hresult == ComHresults.DISP_E_MEMBERNOTFOUND &&
                    (flags & ComTypes.INVOKEKIND.INVOKE_FUNC) != 0 &&
                    (flags & (ComTypes.INVOKEKIND.INVOKE_PROPERTYPUT | ComTypes.INVOKEKIND.INVOKE_PROPERTYPUTREF)) == 0)
                {
                    // Re-invoke with no result argument to accomodate Word
                    hresult = pfnIDispatchInvoke(dispatchPointer,
                                                 memberDispId, &IID_NULL, 0, (ushort)ComTypes.INVOKEKIND.INVOKE_FUNC, pDispParams, null, pExcepInfo, pArgErr);
                }

                return(hresult);
            }
        }
示例#4
0
        public static int InvokePropertySet(this IDispatch dispatch, int dispid, object value)
        {
            int hr = NativeMethods.S_OK;

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

            Variant       pVarResult = default(Variant);
            VariantArgPtr va         = new VariantArgPtr(1);

            var dp = new System.Runtime.InteropServices.ComTypes.DISPPARAMS()
            {
                cArgs             = va.Count,
                rgvarg            = va,
                cNamedArgs        = 1,
                rgdispidNamedArgs = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(int)))
            };

            Marshal.WriteInt32(dp.rgdispidNamedArgs, (int)NativeMethods.DISPID_PROPERTYPUT);

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

            try
            {
                hr = dispatch.Invoke(
                    dispid,
                    ref guid,
                    lcid,
                    flags,
                    ref dp,
                    out pVarResult,
                    ref pExcepInfo,
                    out pArgErr
                    );
            }
            catch
            {
                GlobalExceptionHandler.HandleException();
            }
            finally
            {
                Marshal.FreeCoTaskMem(dp.rgdispidNamedArgs);
                va.Dispose();
            }

            return(hr);
        }
示例#5
0
 void Invoke(
     int dispIdMember,
     ref Guid riid,
     int lcid,
     ComTypes.INVOKEKIND wFlags,
     ref ComTypes.DISPPARAMS pDispParams,
     IntPtr VarResult,
     IntPtr pExcepInfo,
     IntPtr puArgErr);
示例#6
0
        private static object DynamicInvoke(IDispatch dispatch, int dispID, object[] parameters, ComTypes.INVOKEKIND invokeKind)
        {
            Array.Reverse(parameters);
            IntPtr paramsPtr = Marshal.AllocCoTaskMem(parameters.Length * SizeOfVariant);

            ComTypes.DISPPARAMS[] dispParams = new ComTypes.DISPPARAMS[1];
            if (IsSet(invokeKind))
            {
                dispParams[0].cNamedArgs        = 1;
                dispParams[0].rgdispidNamedArgs = Marshal.AllocCoTaskMem(SizeOfVariant);
                Marshal.Copy(new int[] { DISPID_PROPERTYPUT }, 0, dispParams[0].rgdispidNamedArgs, 1);
            }
            else
            {
                dispParams[0].cNamedArgs        = 0;
                dispParams[0].rgdispidNamedArgs = IntPtr.Zero;
            }
            dispParams[0].cArgs  = parameters.Length;
            dispParams[0].rgvarg = paramsPtr;
            try
            {
                int ptr = paramsPtr.ToInt32();
                foreach (object parameter in parameters)
                {
                    Marshal.GetNativeVariantForObject(parameter, new IntPtr(ptr));
                    ptr += SizeOfVariant;
                }
                Guid     guid   = Guid.Empty;
                object[] result = new object[] { null };
                Marshal.ThrowExceptionForHR(dispatch.Invoke(
                                                dispID,
                                                ref guid,
                                                CultureInfo.CurrentCulture.LCID,
                                                (short)invokeKind,
                                                dispParams,
                                                result,
                                                null,
                                                null));
                return(result[0]);
            }
            finally
            {
                if (dispParams[0].rgdispidNamedArgs != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(dispParams[0].rgdispidNamedArgs);
                    dispParams[0].rgdispidNamedArgs = IntPtr.Zero;
                }
                if (dispParams[0].rgvarg != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(dispParams[0].rgvarg);
                    dispParams[0].rgvarg = IntPtr.Zero;
                }
                paramsPtr = IntPtr.Zero;
            }
        }
示例#7
0
 public static object Invoke(this IDispatch dispatch, params object[] args)
 {
     using (var argVariantArrayBlock = new CoTaskMemVariantArgsByRefBlock(args))
     {
         using (var resultVariantBlock = new CoTaskMemVariantBlock())
         {
             var dispArgs = new DISPPARAMS {
                 cArgs = args.Length, rgvarg = argVariantArrayBlock.Addr, cNamedArgs = 0, rgdispidNamedArgs = IntPtr.Zero
             };
             HResult.Check(dispatch.Invoke(SpecialDispIDs.Default, ref iid, 0, DispatchFlags.Method, ref dispArgs, resultVariantBlock.Addr, out _, out _));
             return(Marshal.GetObjectForNativeVariant(resultVariantBlock.Addr));
         }
     }
 }
示例#8
0
 public static object Invoke(this IDispatchEx dispatchEx, bool asConstructor, params object[] args)
 {
     using (var argVariantArrayBlock = new CoTaskMemVariantArgsByRefBlock(args))
     {
         using (var resultVariantBlock = new CoTaskMemVariantBlock())
         {
             EXCEPINFO excepInfo;
             var       dispArgs = new DISPPARAMS {
                 cArgs = args.Length, rgvarg = argVariantArrayBlock.Addr, cNamedArgs = 0, rgdispidNamedArgs = IntPtr.Zero
             };
             HResult.Check(dispatchEx.InvokeEx(SpecialDispIDs.Default, 0, asConstructor ? DispatchFlags.Construct : DispatchFlags.Method, ref dispArgs, resultVariantBlock.Addr, out excepInfo));
             return(Marshal.GetObjectForNativeVariant(resultVariantBlock.Addr));
         }
     }
 }
示例#9
0
        static object InvokePropertyGetter(IDispatch target, int dispId)
        {
            var paramArray = new ComTypes.DISPPARAMS[1];

            paramArray[0].cArgs      = 0;
            paramArray[0].cNamedArgs = 0;

            ComTypes.EXCEPINFO info   = default(ComTypes.EXCEPINFO);
            object             result = null;
            uint puArgErrNotUsed      = 0;

            target.Invoke(dispId, new Guid(), 0x0409, ComTypes.INVOKEKIND.INVOKE_PROPERTYGET,
                          paramArray, out result, out info, out puArgErrNotUsed);

            return(result);
        }
        public static object PropertyGet_NoArgs(IDispatch obj, int memberId)
        {
            var  pDispParams = new ComTypes.DISPPARAMS();
            var  pExcepInfo  = new ComTypes.EXCEPINFO();
            Guid guid        = new Guid();

            int hr = obj.Invoke(memberId, ref guid, 0, (uint)(InvokeKind.DISPATCH_METHOD | InvokeKind.DISPATCH_PROPERTYGET),
                                ref pDispParams, out var pVarResult, ref pExcepInfo, out uint ErrArg);

            if (hr < 0)
            {
                // could expand this to better handle DISP_E_EXCEPTION
                throw Marshal.GetExceptionForHR(hr);
            }

            return(pVarResult);
        }
 /// <summary>
 /// frees all unmanaged memory assoicated with a DISPPARAMS structure
 /// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms221416(v=vs.85).aspx
 /// </summary>
 /// <param name="pDispParams"></param>
 private static void UnprepareDispatchArgs(ComTypes.DISPPARAMS pDispParams)
 {
     if (pDispParams.rgvarg != IntPtr.Zero)
     {
         // free the array of COM VARIANTs
         var variantStructSize      = RdMarshal.SizeOf(typeof(VARIANT));
         var variantArgsArrayOffset = pDispParams.rgvarg;
         var argIndex = 0;
         while (argIndex < pDispParams.cArgs)
         {
             VariantClear(variantArgsArrayOffset);
             variantArgsArrayOffset += variantStructSize;
             argIndex++;
         }
         RdMarshal.FreeHGlobal(pDispParams.rgvarg);
     }
 }
示例#12
0
        static int Invoke(IDispatch dispatch, int memberDispId, out object result)
        {
            Guid emtpyRiid = Guid.Empty;

            ComTypes.DISPPARAMS dispParams = new ComTypes.DISPPARAMS();
            ComTypes.EXCEPINFO  excepInfo  = new ComTypes.EXCEPINFO();
            uint argErr;
            int  hresult = dispatch.TryInvoke(
                memberDispId,
                ref emtpyRiid,
                0,
                ComTypes.INVOKEKIND.INVOKE_PROPERTYGET,
                ref dispParams,
                out result,
                out excepInfo,
                out argErr);

            return(hresult);
        }
示例#13
0
        public static object GetProperty(this IDispatch dispatch, string name, params object[] args)
        {
            if (!MiscHelpers.Try(out int dispid, () => dispatch.GetDispIDForName(name)))
            {
                return(Nonexistent.Value);
            }

            using (var argVariantArrayBlock = new CoTaskMemVariantArgsBlock(args))
            {
                using (var resultVariantBlock = new CoTaskMemVariantBlock())
                {
                    var dispArgs = new DISPPARAMS {
                        cArgs = args.Length, rgvarg = argVariantArrayBlock.Addr, cNamedArgs = 0, rgdispidNamedArgs = IntPtr.Zero
                    };
                    HResult.Check(dispatch.Invoke(dispid, ref iid, 0, DispatchFlags.PropertyGet, ref dispArgs, resultVariantBlock.Addr, out _, out _));
                    return(Marshal.GetObjectForNativeVariant(resultVariantBlock.Addr));
                }
            }
        }
示例#14
0
        private static unsafe int Invoke(IDispatch dispatch, int memberDispId, out object result)
        {
            Guid emtpyRiid = Guid.Empty;

            ComTypes.DISPPARAMS dispParams = new ComTypes.DISPPARAMS();
            Variant             res        = default;
            int hresult = dispatch.TryInvoke(
                memberDispId,
                ref emtpyRiid,
                0,
                ComTypes.INVOKEKIND.INVOKE_PROPERTYGET,
                ref dispParams,
                (IntPtr)(&res),
                IntPtr.Zero,
                IntPtr.Zero);

            result = res.ToObject();

            return(hresult);
        }
        private void ChangeInstallAllUsersUI(IVsdDialogModule uiModule)
        {
            int hr = VSConstants.S_OK;

            NativeMethods.IDispatch properties = (NativeMethods.IDispatch)uiModule.DynamicProperties;
            Guid guid = Guid.Empty;

            string[] names   = new string[] { "InstallAllUsersVisible" };
            int[]    dispIds = new int[] { 0 };
            hr = properties.GetIDsOfNames(ref guid, names, names.Length, 0, dispIds);
            if (dispIds[0] != -1)
            {
                ComTypes.DISPPARAMS[] dispParams = new ComTypes.DISPPARAMS[1];
                dispParams[0].cNamedArgs        = 0;
                dispParams[0].rgdispidNamedArgs = IntPtr.Zero;
                dispParams[0].cArgs             = 1;
                dispParams[0].rgvarg            = Marshal.AllocCoTaskMem(0x1000);
                try
                {
                    Marshal.GetNativeVariantForObject(!InstallAllUsers, dispParams[0].rgvarg);
                    hr = properties.Invoke(
                        dispIds[0],
                        ref guid,
                        CultureInfo.CurrentCulture.LCID,
                        (short)ComTypes.INVOKEKIND.INVOKE_PROPERTYPUT,
                        dispParams,
                        null,
                        null,
                        null);
                }
                finally
                {
                    Marshal.FreeCoTaskMem(dispParams[0].rgvarg);
                    dispParams[0].rgvarg = IntPtr.Zero;
                    if (hr != VSConstants.S_OK)
                    {
                        Marshal.ThrowExceptionForHR(hr);
                    }
                }
            }
        }
示例#16
0
        public static object InvokeMethod(this IDispatchEx dispatchEx, string name, bool ignoreCase, params object[] args)
        {
            var dispid = dispatchEx.GetDispIDForName(name, false, ignoreCase);

            if (dispid == SpecialDispIDs.GetEnumerator)
            {
                return(dispatchEx.GetProperty(SpecialMemberNames.NewEnum, ignoreCase, args));
            }

            using (var argVariantArrayBlock = new CoTaskMemVariantArgsByRefBlock(args))
            {
                using (var resultVariantBlock = new CoTaskMemVariantBlock())
                {
                    var dispArgs = new DISPPARAMS {
                        cArgs = args.Length, rgvarg = argVariantArrayBlock.Addr, cNamedArgs = 0, rgdispidNamedArgs = IntPtr.Zero
                    };
                    HResult.Check(dispatchEx.InvokeEx(dispid, 0, DispatchFlags.Method, ref dispArgs, resultVariantBlock.Addr, out _));
                    return(Marshal.GetObjectForNativeVariant(resultVariantBlock.Addr));
                }
            }
        }
示例#17
0
 public static int InvokeInternal(
     IntPtr thisPtr,
     int dispIdMember,
     ref Guid riid,
     int lcid,
     ComTypes.INVOKEKIND wFlags,
     ref ComTypes.DISPPARAMS pDispParams,
     IntPtr VarResult,
     IntPtr pExcepInfo,
     IntPtr puArgErr)
 {
     try
     {
         var inst = ComInterfaceDispatch.GetInstance <IDispatch>((ComInterfaceDispatch *)thisPtr);
         inst.Invoke(dispIdMember, ref riid, lcid, wFlags, ref pDispParams, VarResult, pExcepInfo, puArgErr);
     }
     catch (Exception e)
     {
         return(e.HResult);
     }
     return(0); // S_OK;
 }
示例#18
0
        public static object GetProperty(this IDispatchEx dispatchEx, string name, bool ignoreCase, params object[] args)
        {
            int dispid;

            if (!MiscHelpers.Try(out dispid, () => dispatchEx.GetDispIDForName(name, false, ignoreCase)))
            {
                return(Nonexistent.Value);
            }

            using (var argVariantArrayBlock = new CoTaskMemVariantArgsBlock(args))
            {
                using (var resultVariantBlock = new CoTaskMemVariantBlock())
                {
                    EXCEPINFO excepInfo;
                    var       dispArgs = new DISPPARAMS {
                        cArgs = args.Length, rgvarg = argVariantArrayBlock.Addr, cNamedArgs = 0, rgdispidNamedArgs = IntPtr.Zero
                    };
                    HResult.Check(dispatchEx.InvokeEx(dispid, 0, DispatchFlags.PropertyGet, ref dispArgs, resultVariantBlock.Addr, out excepInfo));
                    return(Marshal.GetObjectForNativeVariant(resultVariantBlock.Addr));
                }
            }
        }
示例#19
0
        public static object InvokeMethod(this IDispatch dispatch, string name, params object[] args)
        {
            var dispid = dispatch.GetDispIDForName(name);

            if (dispid == SpecialDispIDs.GetEnumerator)
            {
                return(dispatch.GetProperty(SpecialMemberNames.NewEnum, args));
            }

            using (var argVariantArrayBlock = new CoTaskMemVariantArgsByRefBlock(args))
            {
                using (var resultVariantBlock = new CoTaskMemVariantBlock())
                {
                    EXCEPINFO excepInfo;
                    uint      argErr;
                    var       dispArgs = new DISPPARAMS {
                        cArgs = args.Length, rgvarg = argVariantArrayBlock.Addr, cNamedArgs = 0, rgdispidNamedArgs = IntPtr.Zero
                    };
                    HResult.Check(dispatch.Invoke(dispid, iid, 0, DispatchFlags.Method, ref dispArgs, resultVariantBlock.Addr, out excepInfo, out argErr));
                    return(Marshal.GetObjectForNativeVariant(resultVariantBlock.Addr));
                }
            }
        }
        /// <summary>
        /// Convert input args into a contiguous array of real COM VARIANTs for the DISPPARAMS struct used by IDispatch::Invoke
        /// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms221416(v=vs.85).aspx
        /// </summary>
        /// <param name="args">An array of arguments to wrap</param>
        /// <returns><see cref="ComTypes.DISPPARAMS"/> structure ready to pass to IDispatch::Invoke</returns>
        private static ComTypes.DISPPARAMS PrepareDispatchArgs(object[] args)
        {
            var pDispParams = new ComTypes.DISPPARAMS();

            if ((args != null) && (args.Length != 0))
            {
                var variantStructSize = RdMarshal.SizeOf(typeof(VARIANT));
                pDispParams.cArgs = args.Length;

                var argsVariantLength = variantStructSize * pDispParams.cArgs;
                var variantArgsArray  = RdMarshal.AllocHGlobal(argsVariantLength);

                // In IDispatch::Invoke, arguments are passed in reverse order
                var variantArgsArrayOffset = variantArgsArray + argsVariantLength;
                foreach (var arg in args)
                {
                    variantArgsArrayOffset -= variantStructSize;
                    RdMarshal.GetNativeVariantForObject(arg, variantArgsArrayOffset);
                }
                pDispParams.rgvarg = variantArgsArray;
            }
            return(pDispParams);
        }
示例#21
0
        static void Main(string[] args)
        {
            IDispatch disp = (IDispatch)(new Printer());

            int a = 0;

            disp.GetTypeInfoCount(out a);
            var id = new int[6];

            disp.GetIDsOfNames(new Guid(), new string[] { "SetPetName", "DisplayStats", "SetMaxSpeed", "GetMaxSpeed", "GetCurSpeed", "SpeedUp" },
                               6, 1, id);

            var pParam = Marshal.AllocCoTaskMem(15);

            Marshal.GetNativeVariantForObject("HP", pParam);
            object res = 0;

            System.Runtime.InteropServices.ComTypes.DISPPARAMS param = new System.Runtime.InteropServices.ComTypes.DISPPARAMS()
            {
                cArgs             = 1,
                cNamedArgs        = 0,
                rgdispidNamedArgs = IntPtr.Zero,
                rgvarg            = pParam
            };
            disp.Invoke(id[0], new Guid(), 1, new System.Runtime.InteropServices.ComTypes.INVOKEKIND(), param, out res, new IntPtr(), new IntPtr());
            Marshal.GetNativeVariantForObject("20", pParam);
            param.rgvarg = pParam;
            disp.Invoke(id[2], new Guid(), 1, new System.Runtime.InteropServices.ComTypes.INVOKEKIND(), param, out res, new IntPtr(), new IntPtr());
            disp.Invoke(id[1], new Guid(), 1, new System.Runtime.InteropServices.ComTypes.INVOKEKIND(), param, out res, new IntPtr(), new IntPtr());
            disp.Invoke(id[4], new Guid(), 1, new System.Runtime.InteropServices.ComTypes.INVOKEKIND(), param, out res, new IntPtr(), new IntPtr());
            Console.WriteLine("Cur speed = " + res.ToString());
            disp.Invoke(id[5], new Guid(), 1, new System.Runtime.InteropServices.ComTypes.INVOKEKIND(), param, out res, new IntPtr(), new IntPtr());
            disp.Invoke(id[4], new Guid(), 1, new System.Runtime.InteropServices.ComTypes.INVOKEKIND(), param, out res, new IntPtr(), new IntPtr());
            Console.WriteLine("Cur speed = " + res.ToString());

            Console.ReadKey();
        }
示例#22
0
        private string GetName(IDispatch dispatch)
        {
            string theName = null;

            if (nameProperty != null)
            {
                IntPtr ptrDispatch = Marshal.GetIDispatchForObject(dispatch);
                try
                {
                    if (ptrDispatch != IntPtr.Zero)
                    {
                        object typedObject = Marshal.GetTypedObjectForIUnknown(ptrDispatch, comType);
                        if (typedObject != null)
                        {
                            theName = (string)nameProperty.GetValue(typedObject, null);
                        }
                    }
                }
                catch
                {
                    theName = null;
                }
                finally
                {
                    if (ptrDispatch != IntPtr.Zero)
                    {
                        Marshal.Release(ptrDispatch);
                        ptrDispatch = IntPtr.Zero;
                    }
                }
            }
            if (theName == null)
            {
                Guid     guid    = Guid.Empty;
                string[] names   = new string[] { "Name" };
                int[]    dispIds = new int[] { 0 };
                dispatch.GetIDsOfNames(ref guid, names, names.Length, 0, dispIds);
                if (dispIds[0] != -1)
                {
                    ComTypes.DISPPARAMS[] dispParams = new ComTypes.DISPPARAMS[1];
                    dispParams[0].cNamedArgs        = 0;
                    dispParams[0].rgdispidNamedArgs = IntPtr.Zero;
                    dispParams[0].cArgs             = 1;
                    dispParams[0].rgvarg            = Marshal.AllocCoTaskMem(0x1000);
                    try
                    {
                        Marshal.GetNativeVariantForObject(theName, dispParams[0].rgvarg);
                        dispatch.Invoke(
                            dispIds[0],
                            ref guid,
                            CultureInfo.CurrentCulture.LCID,
                            (short)ComTypes.INVOKEKIND.INVOKE_PROPERTYGET,
                            dispParams,
                            null,
                            null,
                            null);
                        object retValue = Marshal.GetObjectForNativeVariant(dispParams[0].rgvarg);
                        if (retValue is string)
                        {
                            theName = (string)retValue;
                        }
                    }
                    finally
                    {
                        Marshal.FreeCoTaskMem(dispParams[0].rgvarg);
                        dispParams[0].rgvarg = IntPtr.Zero;
                    }
                }
            }
            return(theName);
        }
示例#23
0
        /// <summary>
        /// Invoke the COM member
        /// </summary>
        /// <param name="target">IDispatch object</param>
        /// <param name="dispId">Dispatch identifier that identifies the member</param>
        /// <param name="args">Arguments passed in</param>
        /// <param name="byRef">Boolean array that indicates by-Ref parameters</param>
        /// <param name="invokeKind">Invocation kind</param>
        /// <returns></returns>
        internal static object Invoke(IDispatch target, int dispId, object[] args, bool[] byRef, COM.INVOKEKIND invokeKind)
        {
            Diagnostics.Assert(target != null, "Caller makes sure an IDispatch object passed in.");
            Diagnostics.Assert(args == null || byRef == null || args.Length == byRef.Length,
                "If 'args' and 'byRef' are not null, then they should be one-on-one mapping.");

            int argCount = args != null ? args.Length : 0;
            int refCount = byRef != null ? byRef.Count(c => c) : 0;
            IntPtr variantArgArray = IntPtr.Zero, dispIdArray = IntPtr.Zero, tmpVariants = IntPtr.Zero;

            try
            {
                // Package arguments
                if (argCount > 0)
                {
                    variantArgArray = NewVariantArray(argCount);

                    int refIndex = 0;
                    for (int i = 0; i < argCount; i++)
                    {
                        // !! The arguments should be in REVERSED order!!
                        int actualIndex = argCount - i - 1;
                        IntPtr varArgPtr = variantArgArray + s_variantSize * actualIndex;

                        // If need to pass by ref, create a by-ref variant 
                        if (byRef != null && byRef[i])
                        {
                            // Allocate memory for temporary VARIANTs used in by-ref marshalling
                            if (tmpVariants == IntPtr.Zero)
                            {
                                tmpVariants = NewVariantArray(refCount);
                            }

                            // Create a VARIANT that the by-ref VARIANT points to
                            IntPtr tmpVarPtr = tmpVariants + s_variantSize * refIndex;
                            Marshal.GetNativeVariantForObject(args[i], tmpVarPtr);

                            // Create the by-ref VARIANT
                            MakeByRefVariant(tmpVarPtr, varArgPtr);
                            refIndex++;
                        }
                        else
                        {
                            Marshal.GetNativeVariantForObject(args[i], varArgPtr);
                        }
                    }
                }

                var paramArray = new COM.DISPPARAMS[1];
                paramArray[0].rgvarg = variantArgArray;
                paramArray[0].cArgs = argCount;

                if (invokeKind == COM.INVOKEKIND.INVOKE_PROPERTYPUT || invokeKind == COM.INVOKEKIND.INVOKE_PROPERTYPUTREF)
                {
                    // For property putters, the first DISPID argument needs to be DISPID_PROPERTYPUT
                    dispIdArray = Marshal.AllocCoTaskMem(4); // Allocate 4 bytes to hold a 32-bit signed integer
                    Marshal.WriteInt32(dispIdArray, DISPID_PROPERTYPUT);

                    paramArray[0].cNamedArgs = 1;
                    paramArray[0].rgdispidNamedArgs = dispIdArray;
                }
                else
                {
                    // Otherwise, no named parameters are necessary since powershell parser doesn't support named parameter
                    paramArray[0].cNamedArgs = 0;
                    paramArray[0].rgdispidNamedArgs = IntPtr.Zero;
                }

                // Make the call
                EXCEPINFO info = default(EXCEPINFO);
                object result = null;

                try
                {
                    // 'puArgErr' is set when IDispatch.Invoke fails with error code 'DISP_E_PARAMNOTFOUND' and 'DISP_E_TYPEMISMATCH'.
                    // Appropriate exceptions will be thrown in such cases, but FullCLR doesn't use 'puArgErr' in the exception handling, so we also ignore it.
                    uint puArgErrNotUsed = 0;
                    target.Invoke(dispId, s_IID_NULL, LCID_DEFAULT, invokeKind, paramArray, out result, out info, out puArgErrNotUsed);
                }
                catch (Exception innerException)
                {
                    // When 'IDispatch.Invoke' returns error code, CLR will raise exception based on internal HR-to-Exception mapping.
                    // Description of the return code can be found at https://msdn.microsoft.com/en-us/library/windows/desktop/ms221479(v=vs.85).aspx
                    // According to CoreCLR team (yzha), the exception needs to be wrapped as an inner exception of TargetInvocationException.

                    string exceptionMsg = null;
                    if (innerException.HResult == DISP_E_EXCEPTION)
                    {
                        // Invoke was successful but the actual underlying method failed. 
                        // In this case, we use EXCEPINFO to get additional error info.

                        // Use EXCEPINFO.scode or EXCEPINFO.wCode as HR to construct the correct exception.
                        int code = info.scode != 0 ? info.scode : info.wCode;
                        innerException = Marshal.GetExceptionForHR(code, IntPtr.Zero) ?? innerException;

                        // Get the richer error description if it's available.
                        if (info.bstrDescription != IntPtr.Zero)
                        {
                            exceptionMsg = Marshal.PtrToStringBSTR(info.bstrDescription);
                            Marshal.FreeBSTR(info.bstrDescription);
                        }

                        // Free the BSTRs
                        if (info.bstrSource != IntPtr.Zero)
                        {
                            Marshal.FreeBSTR(info.bstrSource);
                        }
                        if (info.bstrHelpFile != IntPtr.Zero)
                        {
                            Marshal.FreeBSTR(info.bstrHelpFile);
                        }
                    }

                    var outerException = exceptionMsg == null
                                              ? new TargetInvocationException(innerException)
                                              : new TargetInvocationException(exceptionMsg, innerException);
                    throw outerException;
                }

                // Now back propagate the by-ref arguments
                if (refCount > 0)
                {
                    for (int i = 0; i < argCount; i++)
                    {
                        // !! The arguments should be in REVERSED order!!
                        int actualIndex = argCount - i - 1;

                        // If need to pass by ref, back propagate 
                        if (byRef != null && byRef[i])
                        {
                            args[i] = Marshal.GetObjectForNativeVariant(variantArgArray + s_variantSize * actualIndex);
                        }
                    }
                }

                return result;
            }
            finally
            {
                // Free the variant argument array
                if (variantArgArray != IntPtr.Zero)
                {
                    for (int i = 0; i < argCount; i++)
                    {
                        VariantClear(variantArgArray + s_variantSize * i);
                    }
                    Marshal.FreeCoTaskMem(variantArgArray);
                }

                // Free the dispId array
                if (dispIdArray != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(dispIdArray);
                }

                // Free the temporary variants created when handling by-Ref arguments
                if (tmpVariants != IntPtr.Zero)
                {
                    for (int i = 0; i < refCount; i++)
                    {
                        VariantClear(tmpVariants + s_variantSize * i);
                    }
                    Marshal.FreeCoTaskMem(tmpVariants);
                }
            }
        }
        unsafe void NativeMethods.IDispatch.Invoke(int dispid, ref Guid riid, int lcid, System.Runtime.InteropServices.ComTypes.INVOKEKIND wFlags, ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams, IntPtr pvarResult, IntPtr pExcepInfo, IntPtr puArgErr)
        {
            ComEventsMethod method = this.FindMethod(dispid);

            if (method != null)
            {
                int      num2;
                object[] args      = new object[pDispParams.cArgs];
                int[]    numArray  = new int[pDispParams.cArgs];
                bool[]   flagArray = new bool[pDispParams.cArgs];
                System.Runtime.InteropServices.Variant *rgvarg = (System.Runtime.InteropServices.Variant *)pDispParams.rgvarg;
                int *rgdispidNamedArgs = (int *)pDispParams.rgdispidNamedArgs;
                int  index             = 0;
                while (index < pDispParams.cNamedArgs)
                {
                    num2            = rgdispidNamedArgs[index];
                    args[num2]      = (rgvarg + index).ToObject();
                    flagArray[num2] = true;
                    if ((rgvarg + index).IsByRef)
                    {
                        numArray[num2] = index;
                    }
                    else
                    {
                        numArray[num2] = -1;
                    }
                    index++;
                }
                num2 = 0;
                while (index < pDispParams.cArgs)
                {
                    while (flagArray[num2])
                    {
                        num2++;
                    }
                    System.Runtime.InteropServices.Variant *variantPtr2 = rgvarg + ((pDispParams.cArgs - 1) - index);
                    args[num2] = variantPtr2.ToObject();
                    if (variantPtr2.IsByRef)
                    {
                        numArray[num2] = (pDispParams.cArgs - 1) - index;
                    }
                    else
                    {
                        numArray[num2] = -1;
                    }
                    num2++;
                    index++;
                }
                object obj2 = method.Invoke(args);
                if (pvarResult != IntPtr.Zero)
                {
                    Marshal.GetNativeVariantForObject(obj2, pvarResult);
                }
                for (index = 0; index < pDispParams.cArgs; index++)
                {
                    int num3 = numArray[index];
                    if (num3 != -1)
                    {
                        (rgvarg + num3).CopyFromIndirect(args[index]);
                    }
                }
            }
        }
示例#25
0
 public void Invoke(object pvInstance, int memid, short wFlags, ref DISPPARAMS pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, out int puArgErr)
 {
     throw new Exception("The method or operation is not implemented.");
 }
示例#26
0
        /// <summary>
        /// Invoke the COM member
        /// </summary>
        /// <param name="target">IDispatch object</param>
        /// <param name="dispId">Dispatch identifier that identifies the member</param>
        /// <param name="args">Arguments passed in</param>
        /// <param name="byRef">Boolean array that indicates by-Ref parameters</param>
        /// <param name="invokeKind">Invocation kind</param>
        /// <returns></returns>
        internal static object Invoke(IDispatch target, int dispId, object[] args, bool[] byRef, COM.INVOKEKIND invokeKind)
        {
            Diagnostics.Assert(target != null, "Caller makes sure an IDispatch object passed in.");
            Diagnostics.Assert(args == null || byRef == null || args.Length == byRef.Length,
                               "If 'args' and 'byRef' are not null, then they should be one-on-one mapping.");

            int argCount = args != null ? args.Length : 0;
            int refCount = byRef != null?byRef.Count(c => c) : 0;

            IntPtr variantArgArray = IntPtr.Zero, dispIdArray = IntPtr.Zero, tmpVariants = IntPtr.Zero;

            try
            {
                // Package arguments
                if (argCount > 0)
                {
                    variantArgArray = NewVariantArray(argCount);

                    int refIndex = 0;
                    for (int i = 0; i < argCount; i++)
                    {
                        // !! The arguments should be in REVERSED order!!
                        int    actualIndex = argCount - i - 1;
                        IntPtr varArgPtr   = variantArgArray + s_variantSize * actualIndex;

                        // If need to pass by ref, create a by-ref variant
                        if (byRef != null && byRef[i])
                        {
                            // Allocate memory for temporary VARIANTs used in by-ref marshalling
                            if (tmpVariants == IntPtr.Zero)
                            {
                                tmpVariants = NewVariantArray(refCount);
                            }

                            // Create a VARIANT that the by-ref VARIANT points to
                            IntPtr tmpVarPtr = tmpVariants + s_variantSize * refIndex;
                            Marshal.GetNativeVariantForObject(args[i], tmpVarPtr);

                            // Create the by-ref VARIANT
                            MakeByRefVariant(tmpVarPtr, varArgPtr);
                            refIndex++;
                        }
                        else
                        {
                            Marshal.GetNativeVariantForObject(args[i], varArgPtr);
                        }
                    }
                }

                var paramArray = new COM.DISPPARAMS[1];
                paramArray[0].rgvarg = variantArgArray;
                paramArray[0].cArgs  = argCount;

                if (invokeKind == COM.INVOKEKIND.INVOKE_PROPERTYPUT || invokeKind == COM.INVOKEKIND.INVOKE_PROPERTYPUTREF)
                {
                    // For property putters, the first DISPID argument needs to be DISPID_PROPERTYPUT
                    dispIdArray = Marshal.AllocCoTaskMem(4); // Allocate 4 bytes to hold a 32-bit signed integer
                    Marshal.WriteInt32(dispIdArray, DISPID_PROPERTYPUT);

                    paramArray[0].cNamedArgs        = 1;
                    paramArray[0].rgdispidNamedArgs = dispIdArray;
                }
                else
                {
                    // Otherwise, no named parameters are necessary since powershell parser doesn't support named parameter
                    paramArray[0].cNamedArgs        = 0;
                    paramArray[0].rgdispidNamedArgs = IntPtr.Zero;
                }

                // Make the call
                EXCEPINFO info   = default(EXCEPINFO);
                object    result = null;

                try
                {
                    // 'puArgErr' is set when IDispatch.Invoke fails with error code 'DISP_E_PARAMNOTFOUND' and 'DISP_E_TYPEMISMATCH'.
                    // Appropriate exceptions will be thrown in such cases, but FullCLR doesn't use 'puArgErr' in the exception handling, so we also ignore it.
                    uint puArgErrNotUsed = 0;
                    target.Invoke(dispId, s_IID_NULL, LCID_DEFAULT, invokeKind, paramArray, out result, out info, out puArgErrNotUsed);
                }
                catch (Exception innerException)
                {
                    // When 'IDispatch.Invoke' returns error code, CLR will raise exception based on internal HR-to-Exception mapping.
                    // Description of the return code can be found at https://msdn.microsoft.com/library/windows/desktop/ms221479(v=vs.85).aspx
                    // According to CoreCLR team (yzha), the exception needs to be wrapped as an inner exception of TargetInvocationException.

                    string exceptionMsg = null;
                    if (innerException.HResult == DISP_E_EXCEPTION)
                    {
                        // Invoke was successful but the actual underlying method failed.
                        // In this case, we use EXCEPINFO to get additional error info.

                        // Use EXCEPINFO.scode or EXCEPINFO.wCode as HR to construct the correct exception.
                        int code = info.scode != 0 ? info.scode : info.wCode;
                        innerException = Marshal.GetExceptionForHR(code, IntPtr.Zero) ?? innerException;

                        // Get the richer error description if it's available.
                        if (info.bstrDescription != IntPtr.Zero)
                        {
                            exceptionMsg = Marshal.PtrToStringBSTR(info.bstrDescription);
                            Marshal.FreeBSTR(info.bstrDescription);
                        }

                        // Free the BSTRs
                        if (info.bstrSource != IntPtr.Zero)
                        {
                            Marshal.FreeBSTR(info.bstrSource);
                        }
                        if (info.bstrHelpFile != IntPtr.Zero)
                        {
                            Marshal.FreeBSTR(info.bstrHelpFile);
                        }
                    }

                    var outerException = exceptionMsg == null
                                              ? new TargetInvocationException(innerException)
                                              : new TargetInvocationException(exceptionMsg, innerException);
                    throw outerException;
                }

                // Now back propagate the by-ref arguments
                if (refCount > 0)
                {
                    for (int i = 0; i < argCount; i++)
                    {
                        // !! The arguments should be in REVERSED order!!
                        int actualIndex = argCount - i - 1;

                        // If need to pass by ref, back propagate
                        if (byRef != null && byRef[i])
                        {
                            args[i] = Marshal.GetObjectForNativeVariant(variantArgArray + s_variantSize * actualIndex);
                        }
                    }
                }

                return(result);
            }
            finally
            {
                // Free the variant argument array
                if (variantArgArray != IntPtr.Zero)
                {
                    for (int i = 0; i < argCount; i++)
                    {
                        VariantClear(variantArgArray + s_variantSize * i);
                    }
                    Marshal.FreeCoTaskMem(variantArgArray);
                }

                // Free the dispId array
                if (dispIdArray != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(dispIdArray);
                }

                // Free the temporary variants created when handling by-Ref arguments
                if (tmpVariants != IntPtr.Zero)
                {
                    for (int i = 0; i < refCount; i++)
                    {
                        VariantClear(tmpVariants + s_variantSize * i);
                    }
                    Marshal.FreeCoTaskMem(tmpVariants);
                }
            }
        }
        private static T Invoke <T>(object source, InvokeFlags invokeFlags, int dispId, params object[] args)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            if (!Enum.IsDefined(typeof(InvokeFlags), invokeFlags))
            {
                throw new ArgumentOutOfRangeException("invokeFlags");
            }
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }

            var    memoryAllocationsToFree = new List <IntPtr>();
            IntPtr rgdispidNamedArgs;
            int    cNamedArgs;

            if ((invokeFlags == InvokeFlags.DISPATCH_PROPERTYPUT) || (invokeFlags == InvokeFlags.DISPATCH_PROPERTYPUTREF))
            {
                // There must be at least one argument specified; only one if it is a non-indexed property and multiple if there are index values as well as the
                // value to set to
                if (args.Length < 1)
                {
                    throw new ArgumentException("At least one argument must be specified when DISPATCH_PROPERTYPUT is requested");
                }

                var pdPutID = Marshal.AllocCoTaskMem(sizeof(Int64));
                Marshal.WriteInt64(pdPutID, DISPID_PROPERTYPUT);
                memoryAllocationsToFree.Add(pdPutID);

                rgdispidNamedArgs = pdPutID;
                cNamedArgs        = 1;
            }
            else
            {
                rgdispidNamedArgs = IntPtr.Zero;
                cNamedArgs        = 0;
            }

            var    variantsToClear = new List <IntPtr>();
            IntPtr rgvarg;

            if (args.Length == 0)
            {
                rgvarg = IntPtr.Zero;
            }
            else
            {
                // We need to allocate enough memory to store a variant for each argument (and then populate this memory)
                rgvarg = Marshal.AllocCoTaskMem(SizeOfNativeVariant * args.Length);
                memoryAllocationsToFree.Add(rgvarg);
                for (var index = 0; index < args.Length; index++)
                {
                    // Note: The "IDispatch::Invoke method (Automation)" page (http://msdn.microsoft.com/en-us/library/windows/desktop/ms221479(v=vs.85).aspx)
                    // states that "Arguments are stored in pDispParams->rgvarg in reverse order" so we'll reverse them here
                    var arg = args[(args.Length - 1) - index];

                    // According to http://stackoverflow.com/a/1866268 it seems like using ToInt64 here will be valid for both 32 and 64 bit machines. While
                    // this may apparently not be the most performant approach, it should do the job.
                    // Don't think we have to worry about pinning any references when we do this manipulation here since we are allocating the array in
                    // unmanaged memory and so the garbage collector won't be moving anything around (and GetNativeVariantForObject copies the reference
                    // and automatic pinning will prevent the GC from interfering while this is happening).
                    var pVariant = new IntPtr(
                        rgvarg.ToInt64() + (SizeOfNativeVariant * index)
                        );
                    Marshal.GetNativeVariantForObject(arg, pVariant);
                    variantsToClear.Add(pVariant);
                }
            }

            var dispParams = new ComTypes.DISPPARAMS()
            {
                cArgs             = args.Length,
                rgvarg            = rgvarg,
                cNamedArgs        = cNamedArgs,
                rgdispidNamedArgs = rgdispidNamedArgs
            };

            try
            {
                var    IID_NULL = new Guid("00000000-0000-0000-0000-000000000000");
                UInt32 pArgErr  = 0;
                object varResult;
                var    excepInfo = new ComTypes.EXCEPINFO();
                var    hrRet     = ((IDispatch)source).Invoke
                                   (
                    dispId,
                    ref IID_NULL,
                    LOCALE_SYSTEM_DEFAULT,
                    (ushort)invokeFlags,
                    ref dispParams,
                    out varResult,
                    ref excepInfo,
                    out pArgErr
                                   );
                if (hrRet != 0)
                {
                    if (excepInfo.bstrDescription == null)
                    {
                        Console.WriteLine($"Exception thrown while accessing {TypeDescriptor.GetClassName(source)} has null bstrDescription");
                    }
                    else
                    {
                        Console.WriteLine($"Exception thrown while accessing {TypeDescriptor.GetClassName(source)} has bstrDescription: \"{excepInfo.bstrDescription}\"");
                    }

                    // Try to translate the exception back into a COMSurvivableException - if this is not possible then fall through to the code below
                    COMSurvivableException.RethrowAsOriginalIfPossible(
                        new COMException(excepInfo.bstrDescription, excepInfo.scode)
                        );
                    var message   = "Failing attempting to invoke method with DispId " + dispId + ": ";
                    var errorType = GetErrorMessageForHResult(hrRet);
                    if (errorType == CommonErrors.DISP_E_MEMBERNOTFOUND)
                    {
                        message += "Member not found";
                    }
                    else if (!string.IsNullOrWhiteSpace(excepInfo.bstrDescription))
                    {
                        message += excepInfo.bstrDescription;
                    }
                    else
                    {
                        message += "Unspecified error";
                        if (errorType != CommonErrors.Unknown)
                        {
                            message += " [" + errorType.ToString() + "]";
                        }
                    }
                    throw new ArgumentException(message);
                }
                return((T)varResult);
            }
            finally
            {
                foreach (var variantToClear in variantsToClear)
                {
                    VariantClear(variantToClear);
                }

                foreach (var memoryAllocationToFree in memoryAllocationsToFree)
                {
                    Marshal.FreeCoTaskMem(memoryAllocationToFree);
                }
            }
        }
示例#28
0
        public static T Invoke <T>(object source, InvokeFlags invokeFlags, int dispId, params object[] args)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            if ((invokeFlags != InvokeFlags.DISPATCH_METHOD) &&
                (invokeFlags != InvokeFlags.DISPATCH_PROPERTYGET) &&
                (invokeFlags != InvokeFlags.DISPATCH_PROPERTYPUT) &&
                (invokeFlags != InvokeFlags.DISPATCH_PROPERTYPUTREF) &&
                (invokeFlags != (InvokeFlags.DISPATCH_METHOD | InvokeFlags.DISPATCH_PROPERTYGET)))
            {
                // It's acceptable to specify both DISPATCH_METHOD and DISPATCH_PROPERTYGET together
                throw new ArgumentOutOfRangeException("invokeFlags");
            }
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }

            var    memoryAllocationsToFree = new List <IntPtr>();
            IntPtr rgdispidNamedArgs;
            int    cNamedArgs;

            if ((invokeFlags == InvokeFlags.DISPATCH_PROPERTYPUT) || (invokeFlags == InvokeFlags.DISPATCH_PROPERTYPUTREF))

            {
                // There must be at least one argument specified; only one if it is a non-indexed property and multiple if there are index values as well as the
                // value to set to
                if (args.Length < 1)
                {
                    throw new ArgumentException("At least one argument must be specified when DISPATCH_PROPERTYPUT(REF) is requested");
                }

                var pdPutID = Marshal.AllocCoTaskMem(sizeof(Int64));
                Marshal.WriteInt64(pdPutID, DISPID_PROPERTYPUT);
                memoryAllocationsToFree.Add(pdPutID);

                rgdispidNamedArgs = pdPutID;
                cNamedArgs        = 1;
            }
            else
            {
                rgdispidNamedArgs = IntPtr.Zero;
                cNamedArgs        = 0;
            }

            var    variantsToClear = new List <IntPtr>();
            IntPtr rgvarg;

            if (args.Length == 0)
            {
                rgvarg = IntPtr.Zero;
            }
            else
            {
                // We need to allocate enough memory to store a variant for each argument (and then populate this memory)
                rgvarg = Marshal.AllocCoTaskMem(SizeOfNativeVariant * args.Length);
                memoryAllocationsToFree.Add(rgvarg);
                for (var index = 0; index < args.Length; index++)
                {
                    // Note: The "IDispatch::Invoke method (Automation)" page (http://msdn.microsoft.com/en-us/library/windows/desktop/ms221479(v=vs.85).aspx)
                    // states that "Arguments are stored in pDispParams->rgvarg in reverse order" so we'll reverse them here
                    var arg = args[(args.Length - 1) - index];

                    // According to http://stackoverflow.com/a/1866268 it seems like using ToInt64 here will be valid for both 32 and 64 bit machines. While
                    // this may apparently not be the most performant approach, it should do the job.
                    // Don't think we have to worry about pinning any references when we do this manipulation here since we are allocating the array in
                    // unmanaged memory and so the garbage collector won't be moving anything around (and GetNativeVariantForObject copies the reference
                    // and automatic pinning will prevent the GC from interfering while this is happening).
                    var pVariant = new IntPtr(
                        rgvarg.ToInt64() + (SizeOfNativeVariant * index)
                        );
                    Marshal.GetNativeVariantForObject(arg, pVariant);
                    variantsToClear.Add(pVariant);
                }
            }

            var dispParams = new ComTypes.DISPPARAMS()
            {
                cArgs             = args.Length,
                rgvarg            = rgvarg,
                cNamedArgs        = cNamedArgs,
                rgdispidNamedArgs = rgdispidNamedArgs
            };

            try
            {
                var    IID_NULL = new Guid("00000000-0000-0000-0000-000000000000");
                UInt32 pArgErr  = 0;
                object varResult;
                var    excepInfo = new ComTypes.EXCEPINFO();
                var    hrRet     = ((IDispatch)source).Invoke
                                   (
                    dispId,
                    ref IID_NULL,
                    LOCALE_SYSTEM_DEFAULT,
                    (ushort)invokeFlags,
                    ref dispParams,
                    out varResult,
                    ref excepInfo,
                    out pArgErr
                                   );
                if (hrRet != 0)
                {
                    var errorType = GetErrorMessageForHResult(hrRet);
                    if (errorType == CommonErrors.DISP_E_MEMBERNOTFOUND)
                    {
                        throw new IDispatchAccessException("Member not found", source, memberNameIfSpecified: null, dispIdIfKnown: dispId, errorType: errorType);
                    }
                    var message = "Failing attempting to invoke method with DispId " + dispId + ": ";
                    if ((excepInfo.bstrDescription ?? "").Trim() == "")
                    {
                        message += "Unspecified error";
                    }
                    else
                    {
                        message += excepInfo.bstrDescription;
                    }
                    if (errorType != CommonErrors.Unknown)
                    {
                        message += " [" + errorType.ToString() + "]";
                    }
                    if (args.Length > 0)
                    {
                        try { Marshal.GetObjectsForNativeVariants(rgvarg, args.Length); }
                        catch (Exception)
                        {
                            // In Visual Studio 2012, if the "Prefer 32-bit" build option is not enabled then arguments do not get written into memory
                            // correctly which will result in the request failing. If an exception has been raised then we can confirm if this is the
                            // problem by trying to pull the arguments back out of the "rgvarg", if this operation fails then the absence of this
                            // build option is most likely the cause.
                            message += " - this may be due to the \"Prefer 32-bit\" option not being enabled in Visual Studio";
                        }
                    }
                    throw new IDispatchAccessException(message, source, memberNameIfSpecified: null, dispIdIfKnown: dispId, errorType: errorType);
                }
                return((T)varResult);
            }
            finally
            {
                foreach (var variantToClear in variantsToClear)
                {
                    VariantClear(variantToClear);
                }

                foreach (var memoryAllocationToFree in memoryAllocationsToFree)
                {
                    Marshal.FreeCoTaskMem(memoryAllocationToFree);
                }
            }
        }
        /// <summary>
        /// Insert a new top level scripting object into the runtime environment of the specified
        /// HTML document.
        /// </summary>
        /// <param name="document">document to insert into</param>
        /// <param name="objectName">top-level name to refer to the object in script</param>
        /// <param name="obj">object to insert (must be marked with ComVisible attribute)</param>
        public static void InjectObjectIntoScriptingEnvironment(IHTMLDocument2 document, string objectName, object obj)
        {
            // ensure that it is marked com-visible
            ComVisibleAttribute[] comVisibleAttributes = (ComVisibleAttribute[])obj.GetType().GetCustomAttributes(typeof(ComVisibleAttribute), false);
            if (comVisibleAttributes.Length == 0 || !comVisibleAttributes[0].Value)
            {
                Debug.Fail("Objects inserted into IHTMLDocument2 scripting environment must be marked with the ComVisible(true) attribute");
                return;
            }

            // implementation constants
            const uint fdexNameEnsure = 0x00000002;
            const uint LOCALE_USER_DEFAULT = 1024;
            const Int16 DISPATCH_PROPERTYPUT = 4;
            const Int32 DISPID_PROPERTYPUT = -3;

            // buffers we will allocate (must free before exiting)
            IntPtr pPropertyPut = IntPtr.Zero;
            IntPtr pObject = IntPtr.Zero;
            try
            {
                // get pointer to IDispatchEx
                object script = document.Script;
                IDispatchEx dispatchEx = (IDispatchEx)script;

                // insert the object into the scripting environment (requires several steps)

                // insert a new dispatch-id for the object
                IntPtr dispId;
                dispatchEx.GetDispID(objectName, fdexNameEnsure, out dispId);

                // initialize structure used to pass the object in
                System.Runtime.InteropServices.ComTypes.DISPPARAMS dispParams = new System.Runtime.InteropServices.ComTypes.DISPPARAMS();
                dispParams.cArgs = 1;
                dispParams.cNamedArgs = 1;

                // indicate that this call to InvokeEx is a property put
                pPropertyPut = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(Int32)));
                Marshal.WriteInt32(pPropertyPut, DISPID_PROPERTYPUT);
                dispParams.rgdispidNamedArgs = pPropertyPut;

                // specify the object to pass to InvokeEx (we think the size of a VARIANT is ~14
                // bytes but we initialize WAY more memory just to be safe)
                pObject = Marshal.AllocCoTaskMem(256);
                Marshal.GetNativeVariantForObject(obj, pObject);
                dispParams.rgvarg = pObject;

                // initialize error structure
                System.Runtime.InteropServices.ComTypes.EXCEPINFO ei = new System.Runtime.InteropServices.ComTypes.EXCEPINFO();

                // set the object into the specified objectName (creates a new top level scripting object)
                dispatchEx.InvokeEx(
                    dispId,					// disp-id of objectName
                    LOCALE_USER_DEFAULT,	// use default locale (should this be en-US?)
                    DISPATCH_PROPERTYPUT,   // specify a property set operation
                    ref dispParams,			// parameters to pass (value to set property to)
                    IntPtr.Zero,			// pointer to result (no result for property put)
                    ref ei,					// pointer to exception structure
                    IntPtr.Zero);			// optional service provider not specified
            }
            finally
            {
                if (pPropertyPut != IntPtr.Zero)
                    Marshal.FreeCoTaskMem(pPropertyPut);
                if (pObject != IntPtr.Zero)
                    Marshal.FreeCoTaskMem(pObject);
            }
        }
示例#30
0
        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);
        }
示例#31
0
        unsafe void NativeMethods.IDispatch.Invoke(
            int dispid,
            ref Guid riid,
            int lcid,
            ComTypes.INVOKEKIND wFlags,
            ref ComTypes.DISPPARAMS pDispParams,
            IntPtr pvarResult,
            IntPtr pExcepInfo,
            IntPtr puArgErr)
        {
            ComEventsMethod method = FindMethod(dispid);

            if (method == null)
            {
                return;
            }

            // notice the unsafe pointers we are using. This is to avoid unnecessary
            // arguments marshalling. see code:ComEventsHelper#ComEventsArgsMarshalling

            object [] args      = new object[pDispParams.cArgs];
            int []    byrefsMap = new int[pDispParams.cArgs];
            bool []   usedArgs  = new bool[pDispParams.cArgs];

            Variant *pvars      = (Variant *)pDispParams.rgvarg;
            int *    pNamedArgs = (int *)pDispParams.rgdispidNamedArgs;

            // copy the named args (positional) as specified
            int i;
            int pos;

            for (i = 0; i < pDispParams.cNamedArgs; i++)
            {
                pos = pNamedArgs[i];

                Variant *pvar = GetVariant(&pvars[i]);
                args[pos]     = pvar->ToObject();
                usedArgs[pos] = true;

                if (pvar->IsByRef)
                {
                    byrefsMap[pos] = i;
                }
                else
                {
                    byrefsMap[pos] = -1;
                }
            }

            // copy the rest of the arguments in the reverse order
            pos = 0;
            for (; i < pDispParams.cArgs; i++)
            {
                // find the next unassigned argument
                while (usedArgs[pos])
                {
                    ++pos;
                }

                Variant *pvar = GetVariant(&pvars[pDispParams.cArgs - 1 - i]);
                args[pos] = pvar->ToObject();

                if (pvar->IsByRef)
                {
                    byrefsMap[pos] = pDispParams.cArgs - 1 - i;
                }
                else
                {
                    byrefsMap[pos] = -1;
                }

                pos++;
            }

            // Do the actual delegate invocation
            object result;

            result = method.Invoke(args);

            // convert result to VARIANT
            if (pvarResult != IntPtr.Zero)
            {
                Marshal.GetNativeVariantForObject(result, pvarResult);
            }

            // Now we need to marshal all the byrefs back
            for (i = 0; i < pDispParams.cArgs; i++)
            {
                int idxToPos = byrefsMap[i];
                if (idxToPos == -1)
                {
                    continue;
                }

                GetVariant(&pvars[idxToPos])->CopyFromIndirect(args[i]);
            }
        }
示例#32
0
        static int Invoke(IDispatch dispatch, int memberDispId, out object result) {
            Guid emtpyRiid = Guid.Empty;
            ComTypes.DISPPARAMS dispParams = new ComTypes.DISPPARAMS();
            ComTypes.EXCEPINFO excepInfo = new ComTypes.EXCEPINFO();
            uint argErr;
            int hresult = dispatch.TryInvoke(
                memberDispId,
                ref emtpyRiid,
                0,
                ComTypes.INVOKEKIND.INVOKE_PROPERTYGET,
                ref dispParams,
                out result,
                out excepInfo,
                out argErr);

            return hresult;
        }
        public static int InvokePropertySet(this IDispatch dispatch, int dispid, object value)
        {
            int hr = NativeMethods.S_OK;

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

            Variant pVarResult = default(Variant);
            VariantArgPtr va = new VariantArgPtr(1);

            var dp = new System.Runtime.InteropServices.ComTypes.DISPPARAMS()
            {
                cArgs = va.Count,
                rgvarg = va,
                cNamedArgs = 1,
                rgdispidNamedArgs = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(int)))
            };

            Marshal.WriteInt32(dp.rgdispidNamedArgs, (int)NativeMethods.DISPID_PROPERTYPUT);

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

            try
            {
                hr = dispatch.Invoke(
                                    dispid,
                                    ref guid,
                                    lcid,
                                    flags,
                                    ref dp,
                                    out pVarResult,
                                    ref pExcepInfo,
                                    out pArgErr
                                    );
            }
            catch
            {
                GlobalExceptionHandler.HandleException();
            }
            finally
            {
                Marshal.FreeCoTaskMem(dp.rgdispidNamedArgs);
                va.Dispose();
            }

            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;
        }
示例#35
0
        static void Main(string[] args)
        {
            object Res = 1;

            int a     = 0;
            Car myCar = new Car();
            //Type type = typeof(Car);
            ICreateCar iCrCar = (ICreateCar)myCar;
            IStats     iStCar = (IStats)myCar;

            //Console.WriteLine("Напишите имя: ");
            //iCrCar.SetPetName(Console.ReadLine());
            //IStats iStCar = (IStats)myCar;
            //string st = "";
            //iStCar.GetPetName(ref st);
            //Console.WriteLine(st);
            iCrCar.SetPetName("Lolipop");
            iCrCar.SetMaxSpeed(67);
            IDispatch disp = (IDispatch)myCar;

            iStCar.DisplayStats();
            disp.GetTypeInfoCount(out a);

            Console.WriteLine(a.ToString());

            int[] t    = new int[1];
            Guid  guid = new Guid();

            disp.GetIDsOfNames(ref guid, new string[] { "GetMaxSpeed" }, 1, 1, t);
            Console.WriteLine("Max speed " + t[0].ToString());

            var arg      = 51;
            var pVariant = Marshal.AllocCoTaskMem(16);

            Marshal.GetNativeVariantForObject(arg, pVariant);
            System.Runtime.InteropServices.ComTypes.DISPPARAMS par = new System.Runtime.InteropServices.ComTypes.DISPPARAMS()
            {
                cArgs             = 1,
                cNamedArgs        = 0,
                rgdispidNamedArgs = IntPtr.Zero,
                rgvarg            = pVariant
            };
            System.Runtime.InteropServices.ComTypes.INVOKEKIND flags = new System.Runtime.InteropServices.ComTypes.INVOKEKIND();
            IntPtr info     = new IntPtr();
            IntPtr puArgErr = new IntPtr();

            disp.Invoke(4, guid, 1, flags, par, out Res, info, puArgErr);
            disp.Invoke(1, guid, 1, flags, par, out Res, info, puArgErr);
            Console.WriteLine("Res = " + Res.ToString());

            var arg_6 = "";

            Marshal.GetNativeVariantForObject(arg_6, pVariant);
            System.Runtime.InteropServices.ComTypes.DISPPARAMS par_6 = new System.Runtime.InteropServices.ComTypes.DISPPARAMS()
            {
                cArgs             = 1,
                cNamedArgs        = 0,
                rgdispidNamedArgs = IntPtr.Zero,
                rgvarg            = pVariant
            };
            System.Runtime.InteropServices.ComTypes.INVOKEKIND flags_6 = new System.Runtime.InteropServices.ComTypes.INVOKEKIND();
            disp.Invoke(6, guid, 1, flags_6, par_6, out Res, info, puArgErr);


            Console.WriteLine("Res = " + Res.ToString());
            Console.ReadKey();
        }
示例#36
0
        static void Main(string[] args)
        {
            // Получаем интерфейс IDispatch
            IDispatch disp = (IDispatch)(new Printer());

            // Получаем число интерфейсов информации типа
            int a = 0;

            disp.GetTypeInfoCount(out a);

            // Массив названий методов
            var namesMaethos = new string[] { "SpeedUp", "QualityUp", "GetMaxSpeed", "GetCurSpeed", "GetCurQuality",
                                              "SetPetName", "SetMaxSpeed", "GetPetName", "DisplayStats" };

            // Массив id методов
            int[] IDs = new int[namesMaethos.Length];

            // Пустой гуид
            Guid guid = new Guid();

            // Получаем массив соответсвующих ID
            disp.GetIDsOfNames(ref guid, namesMaethos, namesMaethos.Length, 1, IDs);

            // Коллекция: ключ - имя метода, значение - ID
            int i           = 0;
            var methodsDict = namesMaethos.ToDictionary(k => k, v => IDs[i++]);

            // Выведем полученные ID
            Console.WriteLine(string.Format("{0, -15} | {1}", "Method name", "ID"));
            foreach (var elem in methodsDict)
            {
                Console.WriteLine(string.Format("{0, -15} | {1}", elem.Key, elem.Value));
            }
            Console.WriteLine("--------------------------");

            // Для получения результата из Get функций
            object result;

            // Последние 2 параметра для Invoke
            var pExcepInfo = new IntPtr();
            var puArgErr   = new IntPtr();

            // 4-й параметр для Invoke
            INVOKEKIND wFlags = new INVOKEKIND();

            // Переменная для передачи аргументов в Set функции
            var pVariant = Marshal.AllocCoTaskMem(10);

            // Преобразуем строку в VARIANT
            Marshal.GetNativeVariantForObject("HP", pVariant);

            // Структура параметров
            DISPPARAMS param = new DISPPARAMS()
            {
                cArgs             = 1,
                cNamedArgs        = 0,
                rgdispidNamedArgs = IntPtr.Zero,
                rgvarg            = pVariant
            };

            // Привсваиваем имя
            disp.Invoke(methodsDict["SetPetName"], guid, 1, wFlags, param, out result, pExcepInfo, puArgErr);

            Marshal.GetNativeVariantForObject(10, pVariant);
            param.rgvarg = pVariant;

            // Привсваиваем максимальную скорость
            disp.Invoke(methodsDict["SetMaxSpeed"], guid, 1, wFlags, param, out result, pExcepInfo, puArgErr);

            // Получаем текущую скорость
            disp.Invoke(methodsDict["GetCurSpeed"], guid, 1, wFlags, param, out result, pExcepInfo, puArgErr);
            Console.WriteLine("Current speed: " + result.ToString());
            int curSpeed = Convert.ToInt32(result);

            // Получаем текущее качество
            disp.Invoke(methodsDict["GetCurQuality"], guid, 1, wFlags, param, out result, pExcepInfo, puArgErr);
            Console.WriteLine("Current quality: " + result.ToString());

            // Получаем максимальную скорость
            disp.Invoke(methodsDict["GetMaxSpeed"], guid, 1, wFlags, param, out result, pExcepInfo, puArgErr);
            int maxSpeed = Convert.ToInt32(result);

            Console.WriteLine("-------------------------");

            for (; curSpeed < maxSpeed; curSpeed++)
            {
                disp.Invoke(methodsDict["SpeedUp"], guid, 1, wFlags, param, out result, pExcepInfo, puArgErr);
                Console.WriteLine("SpeedUp! (+1)");
            }

            Console.WriteLine("-------------------------");

            // Получаем текущую скорость
            disp.Invoke(methodsDict["GetCurSpeed"], guid, 1, wFlags, param, out result, pExcepInfo, puArgErr);
            Console.WriteLine("Current speed: " + result.ToString());

            // Получаем текущее качество
            disp.Invoke(methodsDict["GetCurQuality"], guid, 1, wFlags, param, out result, pExcepInfo, puArgErr);
            Console.WriteLine("Current quality: " + result.ToString());

            // Выводим информацию об объекте
            disp.Invoke(methodsDict["DisplayStats"], guid, 1, wFlags, param, out result, pExcepInfo, puArgErr);

            Console.ReadKey();
        }