private MenuCommand FindCommand(Guid guid, int id, ref int hrReturn)
        {
            hrReturn = (int)Microsoft.VisualStudio.OLE.Interop.Constants.OLECMDERR_E_UNKNOWNGROUP;

            MenuCommand result = null;

            //first query the IMenuCommandService and ask it to FindCommand
            IMenuCommandService menuCommandService = GetService(typeof(IMenuCommandService)) as IMenuCommandService;

            if (menuCommandService != null)
            {
                result = menuCommandService.FindCommand(new CommandID(guid, (int)id));
            }
            //if the IMenuCommandService cames back w/o a command, then ask ourselves
            if (result == null && this != menuCommandService)
            {
                result = FindCommand(guid, (int)id);
            }

            if (result == null)
            {
                ICollection commands = GetCommandList(guid);
                if (commands != null)
                {
                    // The default error now must be "Not Supported" because the command group is known
                    hrReturn = (int)Microsoft.VisualStudio.OLE.Interop.Constants.OLECMDERR_E_NOTSUPPORTED;
                    Debug.WriteLineIf(MENUSERVICE.TraceVerbose, "\t...VSMCS Found group");
                    // Get the list of command inside this group
                    foreach (MenuCommand command in commands)
                    {
                        // we are looping again on the list of commands to check the DynamicItemMatch
                        // but this is unavoidable in this context....
                        // If the command is a OleMenuCommand, then we can try to do a dynamic match
                        IOleMenuCommand vsCommand = command as IOleMenuCommand;
                        if ((null != vsCommand) && (vsCommand.DynamicItemMatch(id)))
                        {
                            Debug.WriteLineIf(MENUSERVICE.TraceVerbose, "\t...VSMCS Found command2");
                            hrReturn = NativeMethods.S_OK;
                            result   = command;
                        }
                    }
                }
            }
            else
            {
                Debug.WriteLineIf(MENUSERVICE.TraceVerbose, "\t... VSMCS Found command");
                hrReturn = NativeMethods.S_OK;
            }
            return(result);
        }
        /// <include file='doc\OleMenuCommandService.uex' path='docs/doc[@for="OleMenuCommandService.IOleCommandTarget.Exec"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// Executes the given command.
        /// </devdoc>
        int IOleCommandTarget.Exec(ref Guid guidGroup, uint nCmdId, uint nCmdExcept, IntPtr pIn, IntPtr vOut)
        {
            const uint vsCmdOptQueryParameterList = 1;

            Guid commandGroup = Guid.Empty;

            try {
                commandGroup = guidGroup;
            }
            catch (NullReferenceException) {
                // Here we assume that the only reason for the exception is a null guidGroup.
                // We do not handle the default command group as definied in the spec for IOleCommandTarget,
                // so we have to return OLECMDERR_E_NOTSUPPORTED.
                return((int)Microsoft.VisualStudio.OLE.Interop.Constants.OLECMDERR_E_NOTSUPPORTED);
            }

            int hr = NativeMethods.S_OK;

            MenuCommand cmd = FindCommand(commandGroup, (int)nCmdId, ref hr);

            // If the command is not supported check if it can be handled by the parent command service
            if ((cmd == null || !cmd.Supported) && _parentTarget != null)
            {
                return(_parentTarget.Exec(ref commandGroup, nCmdId, nCmdExcept, pIn, vOut));
            }
            else if (cmd != null)
            {
                // Try to see if the command is a IOleMenuCommand.
                IOleMenuCommand vsCmd = cmd as IOleMenuCommand;
                // Check the execution flags;
                uint loWord = LoWord(nCmdExcept);
                // If the command is not an OleMenuCommand, it can not handle the show help option.
                if (((uint)OLECMDEXECOPT.OLECMDEXECOPT_SHOWHELP == loWord) && (null == vsCmd))
                {
                    return(NativeMethods.S_OK);
                }
                object o = null;
                if (pIn != IntPtr.Zero)
                {
                    o = Marshal.GetObjectForNativeVariant(pIn);
                }
                if (null == vsCmd)
                {
                    cmd.Invoke(o);
                }
                else
                {
                    switch (loWord)
                    {
                    // Default execution of the command: call the Invoke method
                    case (uint)OLECMDEXECOPT.OLECMDEXECOPT_PROMPTUSER:
                    case (uint)OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER:
                    case (uint)OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT:
                    {
                        IMenuCommandInvokeEx invokeEx = vsCmd as IMenuCommandInvokeEx;
                        if (null != invokeEx)
                        {
                            invokeEx.Invoke(o, vOut, (OLECMDEXECOPT)loWord);
                        }
                        else
                        {
                            vsCmd.Invoke(o, vOut);
                        }
                    }
                    break;

                    case (uint)OLECMDEXECOPT.OLECMDEXECOPT_SHOWHELP:
                        // Check the hi word of the flags to see what kind of help
                        // is needed. We handle only the request for the parameters list.
                        if (vsCmdOptQueryParameterList == HiWord(nCmdExcept) && IntPtr.Zero != vOut)
                        {
                            // In this case vOut is a pointer to a VARIANT that will receive
                            // the parameters description.
                            if (!string.IsNullOrEmpty(vsCmd.ParametersDescription))
                            {
                                Marshal.GetNativeVariantForObject(vsCmd.ParametersDescription, vOut);
                            }
                        }
                        break;

                    default:
                        break;
                    }
                }
            }

            return(hr);
        }