public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
        {
            // Allow automation to work as expected and do nothing if we have
            // no selections and this is not a non-multi-select custom command
            if (this.NotUsedQueryStatus(pguidCmdGroup, cCmds, prgCmds))
            {
                return(this.nextTarget.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText));
            }

            // Check if this is something we support
            IDictionary <uint, ExecCommand> specialCommands = null;

            if (ExecOnAllCommandHandlersByType.TryGetValue(pguidCmdGroup, out var execAllCommands) ||
                SpecialCommandsByType.TryGetValue(pguidCmdGroup, out specialCommands))
            {
                // If we support the command type then see if we support the command
                for (int i = 0; i < cCmds; i++)
                {
                    if ((execAllCommands != null && execAllCommands.Contains(prgCmds[i].cmdID)) ||
                        (specialCommands != null && specialCommands.ContainsKey(prgCmds[i].cmdID)))
                    {
                        prgCmds[i].cmdf = (uint)(OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_SUPPORTED);
                        return(VSConstants.S_OK);
                    }
                }
            }

            // If we do not know the command type then pass on the enquiry.
            return(this.nextTarget.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText));
        }
        public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            try
            {
                // Allow automation to work as expected and do nothing if we have
                // no selections and this is not a non-multi-select custom command
                // or a visual studio command that falls outside the scope of multi-select
                if (this.NotUsedExec(pguidCmdGroup, nCmdID))
                {
                    // We set the expected edit version to null here so that commands that change the
                    // document can run unaffected
                    this.expectedEditVersion = null;
                    return(this.nextTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut));
                }

                // Most commands use the ExecOnAll method and simply execute the input command
                // on the all the selections. We check if the command is one of those here.
                if (ExecOnAllCommandHandlersByType.TryGetValue(pguidCmdGroup, out var execAllCommands) &&
                    execAllCommands.Contains(nCmdID))
                {
                    return(this.ExecOnAll(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut));
                }

                // Some commands have special handlers registered, if this is one of those then use that handler.
                if (SpecialCommandsByType.TryGetValue(pguidCmdGroup, out var specialCommands) &&
                    specialCommands.TryGetValue(nCmdID, out var specialCommand))
                {
                    this.expectedEditVersion = this.textView.TextSnapshot.Version;
                    return(specialCommand(this, ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut));
                }

                // If we got here the command is one we don't recognise. In most cases we simply want
                // to pass through once since most commands of this type are control commands.
                // This does mean that any special navigation and edit commands will not behave as
                // expected (e.g. resharper special navigation)
                // We set the expected edit version to null here so that commands that change the
                // document can run unaffected
                this.expectedEditVersion = null;
                return(this.nextTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut));
            }
            finally
            {
                this.UpdateInMultiEditMode();
            }
        }