One of the most frequently asked questions related to Visual Studio Package and Add-in development concerns how to add additional menus and commands to a specific dropdown or context menu in the Visual Studio IDE.

Adding the menu or command is the easy part. Add-in developers typically use the Commands2.AddNamedCommand2 and Command.AddControl methods, and Visual Studio Package developers use a .CTC resource. In both instances, the hard part is trying to identify the menu or toolbar you actually want to add a new menu or command to.

The Problem:

Trying to identify a specific dropdown or popup menu can be a frustrating experience. Historically, add-in developers have resorted to experimenting with Visual Studio macros to try and discover the appropriate CommandBar name in order to successfully extract a specific CommandBar object from the environment’s DTE.CommandBars collection.  Similarly, Visual Studio Package developers typically resort to searching the various .H and .CTC files included with the Visual Studio SDK. In both instances, success is not always guaranteed.  Especially if the menu or toolbar you were interested in, was implemented by some package or add-in that was developed by a third party, or after the Visual Studio documentation and SDKs were released.

The Solution:

Visual Studio Package developers know that the various menus, toolbars and commands integrated into the Visual Studio IDE, are identified by a unique GUID:ID pair. However, what they may not be aware of is a new undocumented feature introduced with Visual Studio Service Pack 1, which displays this information on demand.

When the DWORD registry value below is set to 1, CTRL+SHIFT is pressed, and you attempt to display a menu or execute a command, a VSDebug Message dialog will be displayed containing the GUID and ID of that menu or command.

 

Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\8.0\General]
"EnableVSIPLogging"=dword:00000001


 (Hint #1, copy the above into an “EnableVSIPLogging.reg” file. And then dblclick the file to merge this value into the registry)

 

For example: Set the above registry value and restart the Visual Studio IDE. Then click on the File menu, press CTRL+SHIFT, then hover over the File.New menu item. This will result in the following dialog being displayed.

 

File.New Menu Data

 

To display similar data for a specific command (menu item), click on the “Help” menu, press CTRL+SHIFT, and then select the “About Microsoft Visual Studio” menu item. This will result in the following dialog being displayed.

 

Help.About Command Data 

(Hint #2: Use CTRL+C to copy the text in the VSDebug dialog to the clipboard)

 

In both instances the Guid and CmdID are the values we are interested in, as this forms the GUID:ID pair that uniquely identifies the command or menu that was to be invoked.

For developers using the Visual Studio Automation model, the GUID:ID of the command can be used with the DTE.ExecuteCommand, and IVsProfferCommands.FindCommandBar methods. Additional details about using IVsProfferCommands.FindCommandBar can be found in the Dr. eX blog entry entitled "Using IVsProfferCommands to retrieve a Visual Studio CommandBar".

For developers authoring Visual Studio Packages, the GUID:ID pair displayed for command data, can be used to enable, disable, or hide existing commands from their IOleCommandTarget.QueryStatus implementations. And the GUID:ID pair for menu data, can be used to parent new commands, menu groups, and controls onto existing menus, via the .CTC resource.

Note, the GuidID, Type, and Flags are internal fields displayed by the VSDebug Message dialog, and are not relevant outside the Visual Studio development team. The NameLoc field is the localized name for the menu. The CanonicalName field is the dotted command name, used in the command window, DTE.ExecuteCommand, and in the KeyBindings dialog. And the LocalizedName field is the localized canonical name for the command.

Happy Coding,
Dr. eX