Recently I was working on a Visual Studio Extension for VS2010, instead of a single item in the the tools menu, what I wanted was a single item with a set of child items.

Strangely enough, documentation on this is quite lacking. So if you need to know how to do it, here's the gist. First, create a standard Visual Studio 2010 extension with the wizard, we'll have some code like the below to start off with, in the OnConnection function:

[csharp]object []contextGUIDS = new object[] { }; Commands2 commands = (Commands2)_applicationObject.Commands; string toolsMenuName = "Tools";

//Place the command on the tools menu.
//Find the MenuBar command bar, which is the top-level command bar holding all the main menu items:
Microsoft.VisualStudio.CommandBars.CommandBar menuBarCommandBar = ((Microsoft.VisualStudio.CommandBars.CommandBars)_applicationObject.CommandBars)["MenuBar"];

//Find the Tools command bar on the MenuBar command bar:
CommandBarControl toolsControl = menuBarCommandBar.Controls[toolsMenuName];
CommandBarPopup toolsPopup = (CommandBarPopup)toolsControl;

//This try/catch block can be duplicated if you wish to add multiple commands to be handled by your Add-in,
// just make sure you also update the QueryStatus/Exec method to include the new command names.
try
{
//Add a command to the Commands collection:
Command command = commands.AddNamedCommand2(_addInInstance, "MyCommand", "MyCommand",
"Executes the command for MyCommand", true, 59, ref contextGUIDS,
(int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled,
(int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton);

//Add a control for the command to the tools menu:
if((command != null) && (toolsPopup != null))
{
	command.AddControl(toolsPopup.CommandBar, 1);
}

}
catch(System.ArgumentException)
{
//If we are here, then the exception is probably because a command with that name
// already exists. If so there is no need to recreate the command and we can
// safely ignore the exception.
}[/csharp]

Now what we're going to do first, is change the code so that we don't actually add a Command named MyCommand, but instead a popup:

[csharp]//This try/catch block can be duplicated if you wish to add multiple commands to be handled by your Add-in, // just make sure you also update the QueryStatus/Exec method to include the new command names. try { // Have we got the tools popup? if(toolsPopup != null) { // Create 'MyCommand' as a popup. var popup = (CommandBarPopup)toolsPopup.Controls.Add(MsoControlType.msoControlPopup); popup.Caption = "MyCommand"; } } catch(System.ArgumentException) { //If we are here, then the exception is probably because a command with that name<br /> // already exists. If so there is no need to recreate the command and we can<br /> // safely ignore the exception. }[/csharp]

Now that we have the popup object, we can create commands and add them to the popup instead:

[csharp]// Have we got the tools popup? if(toolsPopup != null) { // Create 'MyCommand' as a popup. var popup = (CommandBarPopup)toolsPopup.Controls.Add(MsoControlType.msoControlPopup); popup.Caption = "MyCommand"; // Create sub item 1. var subItem1Command = commands.AddNamedCommand2(_addInInstance, "MyCommand1", "My Command Subitem 1", "My Command Subitem 1", true, 59, ref contextGUIDS); // Add it. subItem1Command.AddControl(popup.CommandBar, 1); // Create sub item 2. var subItem2Command = commands.AddNamedCommand2(_addInInstance, "MyCommand2", "My Command Subitem 2", "My Command Subitem 2", true, 59, ref contextGUIDS); // Add it. subItem2Command.AddControl(popup.CommandBar, 2); }[/csharp]

Now that we have made these changes, if we run the addin, we get a menu structure like this: