Tuesday, 1 May 2018

C# - COM Interop - Before dynamic to avoid PIAs one needed to call IDispatch

So I had researched an answer to a SO question where OP wanted to avoid a method call throwing an error and also wanted to not have to use On Error Resume Next. I recognise this situation. To avoid OERN I recommend burying the error throwing code in a .NET DLL. I got a solution using the dynamic keyword working because that avoids any dependency on an Primary Interop Assembly. But given my ongoing interest in IDispatch I also developed an IDispatch solution.

So might as well share the code


using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;

namespace SupportsGroupItemsByIDispatchLib
{

    public interface ISupportsGroupItemsByIDispatch
    {
        bool SupportsGroupItemsByIDispatch(object shp);
    }

    [ClassInterface(ClassInterfaceType.None)]
    [ComDefaultInterface(typeof(ISupportsGroupItemsByIDispatch))]
    public class CSupportsGroupItemsByIDispatch : ISupportsGroupItemsByIDispatch
    {
        [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00020400-0000-0000-C000-000000000046")]
        private interface IDispatch
        {
            int GetTypeInfoCount();
            [return: MarshalAs(UnmanagedType.Interface)]
            ITypeInfo GetTypeInfo([In, MarshalAs(UnmanagedType.U4)] int iTInfo, [In, MarshalAs(UnmanagedType.U4)] int lcid);
            void GetIDsOfNames([In] ref Guid riid, [In, MarshalAs(UnmanagedType.LPArray)] string[] rgszNames, [In, MarshalAs(UnmanagedType.U4)] int cNames, [In, MarshalAs(UnmanagedType.U4)] int lcid, [Out, MarshalAs(UnmanagedType.LPArray)] int[] rgDispId);
            int Invoke
            (
                int dispIdMember,
                ref Guid riid,
                uint lcid,
                ushort wFlags,
                ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams,
                out object pVarResult,
                ref System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo,
                IntPtr[] pArgErr
            );
        }

        public const int lDISPID_GROUPITEMS = 108;
        public const int DISPATCH_PROPERTYGET = 2;
        bool ISupportsGroupItemsByIDispatch.SupportsGroupItemsByIDispatch(object shp)
        {
            bool bSupportsGroupItems = false;

            try
            {
                Guid nullGuid = new Guid("00000000000000000000000000000000");

                IDispatch disp = (IDispatch)shp;
                object grpItems;
                System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo = new System.Runtime.InteropServices.ComTypes.EXCEPINFO();


                //
                System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams = new System.Runtime.InteropServices.ComTypes.DISPPARAMS();
                pDispParams.cArgs = 0;

                //
                IntPtr[] pArgErr = new IntPtr[1];

                int dispInvokeRet;
                dispInvokeRet = disp.Invoke(lDISPID_GROUPITEMS, ref nullGuid, 0, DISPATCH_PROPERTYGET, pDispParams, out grpItems, ref pExcepInfo, pArgErr);

                bSupportsGroupItems = true;

            }
            catch (Exception)
            {
                // bury the error
                //throw new Exception("Error :" + ex.Message);

            }
            return bSupportsGroupItems;
        }
    }
}



No comments:

Post a Comment