Logo
HOWTO: Get a CommandBar by Guid and Id rather than by name from a Visual Studio add-in

Author: Carlos J. Quintero (Microsoft MVP) Applies to: Microsoft Visual Studio 2005
Date: February 2011   Microsoft Visual Studio 2008
Updated: March 2013   Microsoft Visual Studio 2010
      Microsoft Visual Studio 2012
Introduction

CommandBars of Visual Studio are uniquely identified by a Guid and an Id. They can also have a name (or not) and that name may not be unique (for example there are several commandbars with the name "View"). You can get a commandbar by name from the DTE.CommandBars collection, guessing the name as explained in the article HOWTO: Guessing the name of a command bar to add a custom menu entry in Visual Studio .NET add-ins.

This article explains how to get a CommandBar knowing its Guid and Id. You can guess the Guid and Id of a commandbar through two approaches:

More Information

The following add-in shows how to get the following commandbars by Guid and Id:

  • A menu bar (the main menu bar of Visual Studio).
  • A commandbar popup which is a child of a commandbar (the "Tools" commandbar of the main menu). This only works on Visual Studio 2005 and 2008, but not on VS 2010 and higher (you get an ArgumentException "Value does not fall within the expected range"). To use an approach that works on all Visual Studio versions, see HOWTO: Locate commandbars in international versions of Visual Studio.
  • A commandbar popup which is a context menu (The "Code Window" context menu). In this case Visual Studio 2005 and 2008 require that you call DTE.CommandBars before, otherwise you get a COMException 0x80004005.
Language: VB.NET   Copy Code Copy Code (IE only)
Imports System
Imports Microsoft.VisualStudio.CommandBars
Imports Extensibility
Imports EnvDTE
Imports EnvDTE80
Imports System.Windows.Forms
Imports System.Runtime.InteropServices

Public Class Connect
   Implements IDTExtensibility2

   <ComVisible(True), ComImport(), Guid("6D5140C1-7436-11CE-8034-00AA006009FA"), _
      InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _
   Friend Interface IOleServiceProvider
      <PreserveSig()> _
      Function QueryService(<InAttribute()> ByRef guidService As Guid, _
      <InAttribute()> ByRef riid As Guid,<MarshalAs(UnmanagedType.Interface)> ByRef ppvObject As Object) As Integer
   End Interface

   Private _dte As EnvDTE.DTE

   Public Sub OnConnection(ByVal application As Object, ByVal connectMode As ext_ConnectMode, ByVal addInInst As Object, _
      ByRef custom As Array) Implements IDTExtensibility2.OnConnection

      _dte = CType(application, DTE)

      Select Case connectMode

         Case ext_ConnectMode.ext_cm_Startup
            ' OnStartupComplete will be called

         Case ext_ConnectMode.ext_cm_AfterStartup
            InitializeAddIn()

      End Select

   End Sub

   Public Sub OnStartupComplete(ByRef custom As Array) Implements IDTExtensibility2.OnStartupComplete

      InitializeAddIn()

   End Sub

   Private Sub InitializeAddIn()

      Dim menuCommandBar As CommandBar
      Dim toolsCommandBar As CommandBar
      Dim codeWindowCommandBar As CommandBar
      Dim profferCommands As EnvDTE.IVsProfferCommands
      Dim commandBars As Object

      Try

         Select Case _dte.Version

            Case "8.0", "9.0"

               ' This is required in VS 2005 and 2008 to retrieve commandbars that are not initialized when Visual Studio is loaded,
               ' such as the Code Window context menu. It is not required in VS 2010
               commandBars = _dte.CommandBars

         End Select

         profferCommands = GetIVsProfferCommands()

         menuCommandBar = GetCommandBarById(profferCommands, "D309F791-903F-11D0-9EFC-00A0C911004F", 0)
         MessageBox.Show(menuCommandBar.Name)

         Select Case _dte.Version

            Case "8.0", "9.0"

               toolsCommandBar = GetCommandBarById(profferCommands, "D309F791-903F-11D0-9EFC-00A0C911004F", &H85)
               MessageBox.Show(toolsCommandBar.Name)

            Case Else

               ' The approach above of getting CommandBarPopups that are children of a CommandBar doesn't work on VS 2010
               ' To locate CommandBarPopups that are children of a CommandBar use the following instead, which works with all VS versions:
               ' HOWTO: Locate commandbars in international versions of Visual Studio
               ' http://www.mztools.com/articles/2007/MZ2007002.aspx

         End Select

         codeWindowCommandBar = GetCommandBarById(profferCommands, "D309F791-903F-11D0-9EFC-00A0C911004F", &H40D)
         MessageBox.Show(codeWindowCommandBar.Name)

      Catch ex As Exception

         MessageBox.Show(ex.ToString)

      End Try

   End Sub

   Private Function GetIVsProfferCommands() As EnvDTE.IVsProfferCommands

      Dim profferCommands As EnvDTE.IVsProfferCommands
      Dim oleServiceProvider As IOleServiceProvider
      Dim guid As Guid
      Dim service As Object = Nothing

      oleServiceProvider = DirectCast(_dte, IOleServiceProvider)

      guid = GetType(EnvDTE.IVsProfferCommands).GUID

      oleServiceProvider.QueryService(guid, guid, service)

      profferCommands = DirectCast(service, EnvDTE.IVsProfferCommands)

      Return profferCommands

   End Function

   Private Function GetCommandBarById(ByVal profferCommands As EnvDTE.IVsProfferCommands, ByVal guidString As String, _
      ByVal id As UInteger) As CommandBar

      Dim commandBar As CommandBar
      Dim guid As Guid

      guid = New Guid(guidString)

      commandBar = DirectCast(profferCommands.FindCommandBar(IntPtr.Zero, guid, id), CommandBar)

      Return commandBar

   End Function

   Public Sub OnDisconnection(ByVal disconnectMode As ext_DisconnectMode, ByRef custom As Array) _
      Implements IDTExtensibility2.OnDisconnection

   End Sub

   Public Sub OnAddInsUpdate(ByRef custom As Array) Implements IDTExtensibility2.OnAddInsUpdate
   End Sub

   Public Sub OnBeginShutdown(ByRef custom As Array) Implements IDTExtensibility2.OnBeginShutdown
   End Sub

End Class
Language: C#   Copy Code Copy Code (IE only)
using System;
using Extensibility;
using EnvDTE;
using EnvDTE80;
using System.Runtime.InteropServices;
using Microsoft.VisualStudio.CommandBars;
using System.Windows.Forms;

namespace MyAddin1
{
   public class Connect : IDTExtensibility2
   {

      [ComVisible(true), ComImport(), Guid("6D5140C1-7436-11CE-8034-00AA006009FA"), _
         InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
      internal interface IOleServiceProvider
      {
         [PreserveSig()]
         int QueryService([InAttribute()] ref Guid guidService, [InAttribute()] ref Guid riid, 
            [MarshalAs(UnmanagedType.Interface)] ref object ppvObject);
      }

      private DTE _dte;

      public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
      {
         _dte = (DTE)application;
         
         switch (connectMode)
         {
            case ext_ConnectMode.ext_cm_Startup:
               // OnStartupComplete will be called
               break;

            case ext_ConnectMode.ext_cm_AfterStartup:
               InitializeAddIn();
               break;
         }
      }
      public void OnStartupComplete(ref Array custom)
      {
         InitializeAddIn();
      }
      private void InitializeAddIn()
      {
         CommandBar menuCommandBar;
         CommandBar toolsCommandBar;
         CommandBar codeWindowCommandBar;
         EnvDTE.IVsProfferCommands profferCommands;
         object commandBars;

         try
         {
            switch (_dte.Version)
            {
               case "8.0":
               case "9.0":
                  // This is required in VS 2005 and 2008 to retrieve commandbars that are not initialized when Visual Studio is loaded,
                  // such as the Code Window context menu. It is not required in VS 2010
                  commandBars = _dte.CommandBars;
                  break;
            }

            profferCommands = GetIVsProfferCommands();

            menuCommandBar = GetCommandBarById(profferCommands, "D309F791-903F-11D0-9EFC-00A0C911004F", 0);
            MessageBox.Show(menuCommandBar.Name);

            switch (_dte.Version)
            {
               case "8.0":
               case "9.0":
               
                  toolsCommandBar = GetCommandBarById(profferCommands, "D309F791-903F-11D0-9EFC-00A0C911004F", 0x85);
                  MessageBox.Show(toolsCommandBar.Name);
                  break;
               
               default:
                                    
                  // The approach above of getting CommandBarPopups that are children of a CommandBar doesn't work on VS 2010
                  // To locate CommandBarPopups that are children of a CommandBar use the following instead, which works with all VS versions:
                  // HOWTO: Locate commandbars in international versions of Visual Studio
                  // http://www.mztools.com/articles/2007/MZ2007002.aspx

                  break;
            }
            
            codeWindowCommandBar = GetCommandBarById(profferCommands, "D309F791-903F-11D0-9EFC-00A0C911004F", 0x40D);
            MessageBox.Show(codeWindowCommandBar.Name);
         }
         catch (Exception ex)
         {
            MessageBox.Show(ex.ToString());
         }

      }

      private EnvDTE.IVsProfferCommands GetIVsProfferCommands()
      {
         EnvDTE.IVsProfferCommands profferCommands;
         IOleServiceProvider oleServiceProvider;
         Guid guid;
         object service = null;

         oleServiceProvider = (IOleServiceProvider) (_dte);

         guid = (typeof(EnvDTE.IVsProfferCommands)).GUID;

         oleServiceProvider.QueryService(ref guid, ref guid, ref service);

         profferCommands = (EnvDTE.IVsProfferCommands) service;

         return profferCommands;
      }

      private CommandBar GetCommandBarById(EnvDTE.IVsProfferCommands profferCommands, string guidString, uint id)
      {
         CommandBar commandBar;
         Guid guid;

         guid = new Guid(guidString);

         commandBar = (CommandBar) profferCommands.FindCommandBar(IntPtr.Zero, ref guid, id);

         return commandBar;
      }

      public void OnDisconnection(ext_DisconnectMode disconnectMode, ref Array custom)
      {
      }

      public void OnAddInsUpdate(ref Array custom)
      {
      }
       
      public void OnBeginShutdown(ref Array custom)
      {
      }
   }
}

Related articles



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


Top