ProgrammerAtWork ProgrammerAtWork - 13 days ago 6
C# Question

How to capture Visual Studio commands in a VSPackage Plugin?

I'm trying to make a plugin that captures the

edit.copy
command of visual studio, and skips it if nothing is selected.

I have installed the Visual Studio SDK and created a VSPackage project. My initialize method curently looks like the following:

private EnvDTE.DTE m_objDTE = null;
protected override void Initialize()
{
Debug.WriteLine (string.Format(CultureInfo.CurrentCulture, "Entering Initialize() of: {0}", this.ToString()));
base.Initialize();

m_objDTE = (EnvDTE.DTE)GetService(typeof(EnvDTE.DTE));

m_objDTE.Events.CommandEvents.BeforeExecute += (
string Guid,
int ID,
Object CustomIn,
Object CustomOut,
ref bool CancelDefault
) =>
{
EnvDTE.Command objCommand;
string commandName = "";

objCommand = m_objDTE.Commands.Item(Guid, ID);
if (objCommand != null)
{
commandName = objCommand.Name;

if (string.IsNullOrEmpty(commandName))
{
commandName = "<unnamed>";
}
}

Debug.WriteLine("Before executing command with Guid=" + Guid + " and ID=" + ID + " named " + commandName);


};

}


The
Initialize()
method is called when a solution is opened, I have the
[ProvideAutoLoad(UIContextGuids80.SolutionExists)]
tag added to my package. But the BeforeExecute is not called when I do things, like pressing
ctrl + c
which is a command, With this code I expect all commands to be printed in the debug console, why isn't this happening?

Answer

Here is the code I used that works:

using System;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
using System.ComponentModel.Design;
using Microsoft.Win32;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.Shell;
using EnvDTE;

namespace Dinto.NoCopy
{
    [PackageRegistration(UseManagedResourcesOnly = true)]
    [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
    [Guid(GuidList.guidNoCopyPkgString)]
    [ProvideAutoLoad(UIContextGuids80.SolutionExists)]
    public sealed class NoCopyPackage : Package
    {
        public NoCopyPackage()
        {
            Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering constructor for: {0}", this.ToString()));
        }

        #region Package Members


        private EnvDTE.DTE m_objDTE = null;
        private CommandEvents _pasteEvent;

        protected override void Initialize()
        {
            Debug.WriteLine (string.Format(CultureInfo.CurrentCulture, "Entering Initialize() of: {0}", this.ToString()));
            base.Initialize();

            m_objDTE = (DTE)GetService(typeof(DTE));

            var pasteGuid = typeof(VSConstants.VSStd97CmdID).GUID.ToString("B");
            var pasteID = (int)VSConstants.VSStd97CmdID.Copy;

            _pasteEvent = m_objDTE.Events.CommandEvents[pasteGuid, pasteID];
            _pasteEvent.BeforeExecute += CopyRead;

        }
        #endregion

        private void CopyRead (
          string Guid,
          int ID,
          Object CustomIn,
          Object CustomOut,
          ref bool CancelDefault
          )
        {
          EnvDTE.Command objCommand;
          string commandName = "";


          objCommand = m_objDTE.Commands.Item(Guid, ID);
          if (objCommand != null)
          {
            commandName = objCommand.Name;
          }

          if (commandName.Equals("Edit.Copy"))
          {
            TextSelection textSelection = (TextSelection)m_objDTE.ActiveDocument.Selection;

            if (textSelection.IsEmpty)
            {
              CancelDefault = true;
            }
          }
        }

    }
}
Comments