HOWTO: Locate the index of a CommandBarControl on a Commandbar to add a control or menu before or after it.

Author: Carlos J. Quintero (Microsoft MVP) Applies to: Microsoft Visual Studio .NET 2002
Date: March 2010   Microsoft Visual Studio .NET 2003
Updated: March 2013   Microsoft Visual Studio 2005
      Microsoft Visual Studio 2008
      Microsoft Visual Studio 2010
      Microsoft Visual Studio 2012

When add-ins want to add their buttons and commandbarpopups on an existing built-in Visual Studio commandbar, most of the time they want to add them at the start or at the end of the existing controls, so they use either 1 or parentCommandBar.Controls.Count + 1 when using the optional parameter of the methods that create CommandbarButtons or CommandbarPopups to specify the position:

  • For CommandBarButtons created from commands (passing the parent CommandBar in the Owner parameter):


    Command.AddControl(ByVal Owner As Object, Optional ByVal Position As Integer = 1)


    Command.AddControl(object Owner, int Position = 1)
  • For CommandbarPopups (passing the MsoControlType.msoControlPopup value in the Type parameter):


    CommandBar.Controls.Add(Optional ByVal Type As Object = Nothing, Optional ByVal Id As Object = Nothing, Optional ByVal Parameter As Object = Nothing, Optional ByVal Before As Object = Nothing, Optional ByVal Temporary As Object = Nothing)
    CommandBar.Controls.Add(object Type, object Id, object Parameter, object Before, object Temporary)

However, sometimes they want to add them before or after a specific existing control. A typical scenario is when an add-in wants to add its menu just before or after the "Tools" menu of Visual Studio in the menu bar. For these scenarios the add-in must get the exact index of a control on a commandbar. This article explains how to know that position taking into account that controls don't have a Name property like CommandBars, just a Caption property that can be localized and therefore it is not reliable to locate a control on a CommandBar.

More Information

The items on a CommandBar are always of the type CommandBarControl. Since a CommandBar can contain buttons or popups, in turn a CommandBarControl can be a CommandBarButton or a CommandBarPopup, respectively. So, to locate a specific CommandbarControl you need to iterate the CommandBar.Controls collection, and for each CommandBarControl, check its kind (CommandBarButton or CommandBarPopup):

  • For a CommandBarButton you can't know its identity using the Caption property because it can be localized. Rather, you can get the command behind it using the approach described in the article HOWTO: Retrieve the Command that created a CommandBarControl from a Visual Studio add-in or macro. Once you have the EnvDTE.Command you can use its Command.Name property (which is never localized) to identify the button. For example, the "New Project..." CommandBarButton on the "File" CommandBar, which in Spanish would have the "Nuevo proyecto..." caption, has the "File.NewProject" command name in both languages.
  • For a CommandBarPopup you can use its CommandBarPopup.CommandBar.Name property, that is never localized either.

The following macro shows how to retrieve the indexes of the "Open Project..." button and "Recent Projects" popup on the File menu of Visual Studio:

Language: VB.NET   Copy Code Copy Code (IE only)
Sub Macro1()

   Dim commandBars As Microsoft.VisualStudio.CommandBars.CommandBars
   Dim fileCommandBar As Microsoft.VisualStudio.CommandBars.CommandBar
   Dim commandBarControl As Microsoft.VisualStudio.CommandBars.CommandBarControl
   Dim commandBarButton As Microsoft.VisualStudio.CommandBars.CommandBarButton
   Dim commandBarPopup As Microsoft.VisualStudio.CommandBars.CommandBarPopup
   Dim guid As String
   Dim id As Integer
   Dim command As Command

   commandBars = DirectCast(DTE.CommandBars, Microsoft.VisualStudio.CommandBars.CommandBars)

   fileCommandBar = commandBars.Item("File")

   For Each commandBarControl In fileCommandBar.Controls

      If commandBarControl.Visible Then

         If TypeOf commandBarControl Is Microsoft.VisualStudio.CommandBars.CommandBarButton Then

            DTE.Commands.CommandInfo(commandBarControl, guid, id)

            command = DTE.Commands.Item(guid, id)

            If command.Name = "File.OpenProject" Then
               MessageBox.Show("Button with caption '" & commandBarControl.Caption & "'" & " has index " & commandBarControl.Index)
            End If

         ElseIf TypeOf commandBarControl Is Microsoft.VisualStudio.CommandBars.CommandBarPopup Then

            commandBarPopup = DirectCast(commandBarControl, Microsoft.VisualStudio.CommandBars.CommandBarPopup)

            If commandBarPopup.CommandBar.Name = "Recent Projects" Then
               MessageBox.Show("Popup with caption '" & commandBarControl.Caption & "' has index " & commandBarControl.Index)
            End If

         End If

      End If


End Sub

Related articles

Go to the 'Visual Studio Extensibility (VSX)' web site for more articles like this (Articles section)