---
title: "Declarative Visual Studio addin buttons with icons"
url: "https://osherove.com/blog/2008/8/2/declarative-visual-studio-addin-buttons-with-icons.md"
canonical: "https://osherove.com/blog/2008/8/2/declarative-visual-studio-addin-buttons-with-icons.html"
published: "2008-08-02T13:21:00"
updated: "2008-08-02T13:21:00"
tags: [".NET", ".Net 2.0", "Extensibility", "General Software Devel..."]
author: "Roy Osherove"
description: "in the previous pos t I said how I hated doing custom icons for addins and showed how you can make it work. In this post I’ll show what I feel is a better way of managing the actions on the buttons, and how to…"
usage: "Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page)."
license: "https://creativecommons.org/licenses/by/4.0/"
---

# Declarative Visual Studio addin buttons with icons

By Roy Osherove August 2, 2008 In [.NET](https://osherove.com/blog/category/net), [.Net 2.0](https://osherove.com/blog/category/net-2-0), [Extensibility](https://osherove.com/blog/category/extensibility), [General Software Devel...](https://osherove.com/blog/category/general-software-devel)

**Historical article** · Originally published August 2, 2008; technical details may be outdated.

in the [previous pos](http://weblogs.asp.net/rosherove/archive/2008/08/02/howto-set-custom-visual-studio-addin-menu-icons-without-a-satellite-dll.aspx)t I said how I hated doing custom icons for addins and showed how you can make it work. In this post I’ll show what I feel is a better way of managing the actions on the buttons, and how to declaratively create buttons with icons that are loaded automatically.

First, You can [download the source here](http://files.osherove.com/downloads/DeclarativeAddinButtons.zip). What you’ll find there are a bunch of helper classes and a base class that allows you to declare an addin button like this:

    \[AddinButtonCaption("yo","some description")\]

    \[AddinButtonIconName("boldhs.bmp")\]

    \[AddinUnderMenuName("MenuBar","Tools")\]

    public class HelloWorldAddinAction:AddinActionBase

    {

        public HelloWorldAddinAction(CommandBarButton relatedButton)

            : base(relatedButton){}

        public override void Execute()

        {

            MessageBox.Show("hello there!");

        }

    }

You set the caption, icon and location of the addin button using the attributes on top of the class. You need to inherit from AddinActionBase and override the Execute() method to do anything useful. You also get access to the related button to change its properties later on.  The icon path is hard coded to be the location of the running assembly\\icons.

here is another button that switches icons and text and is located under the “Test” menu:

    \[AddinButtonCaption("Another Button!","and descccc")\]

    \[AddinButtonIconName("book\_openhs.bmp")\]

    \[AddinUnderMenuName("MenuBar","Test")\]

    class ActionThatReplacesItsIcon:AddinActionBase

    {

        private bool isOn \= false;

        public ActionThatReplacesItsIcon(CommandBarButton relatedButton)

            : base(relatedButton)

        {

        }

        public override void Execute()

        {

            MessageBox.Show("Another one!");

            isOn \= !isOn;

            if(!isOn)

                SetButtonIcon("book\_anglehs.bmp");

            else

                SetButtonIcon("book\_openhs.bmp");

            RelatedButton.Caption \= isOn.ToString();

        }

    }

It uses the “RelatedButton” property to set caption on the button, and uses a derived method “SetButtonIcon” to change icons.

So – how do you initialize all these buttons? in the “OnConnection” method, you call a special “AddinReflector” class that does all the work for you:

        private DTE2 \_applicationObject;

        private AddIn \_addInInstance;

        public void OnConnection(object application, ext\_ConnectMode connectMode, object addInInst, ref Array custom)

        {

            \_applicationObject \= (DTE2)application;

            \_addInInstance \= (AddIn)addInInst;

            if(connectMode \== ext\_ConnectMode.ext\_cm\_UISetup)

            {

                Commands2 commands \= (Commands2)\_applicationObject.Commands;

                AddinReflector.LoadAllButtonsInCurrentAssembly(commands, \_addInInstance,\_applicationObject);

            }

        }

You need override another method to make the methods execute correctly:

public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)

        {

            handled \= false;

            if(executeOption \== vsCommandExecOption.vsCommandExecOptionDoDefault)

            {

                AddinActionBase action \= AddinRegistry.GetActionByName(commandName);

                action.Execute();

                handled\=true;

            }

        }

The idea is simplicity: you want to add another button? with an icon? just create a simple class with some attributes and you’re done.

You can [download the source here](http://files.osherove.com/downloads/DeclarativeAddinButtons.zip). 

- Icons are hard coded to be found under \[current assembly location\]\\icons
- the classes need to be declared in the current assembly (easily changed if you’d like)

## More in .NET

[All posts in .NET](https://osherove.com/blog/category/net)

- Aug 3, 2008

    ### [VS Addins Revisited: Declarative button order and location with a DSL](https://osherove.com/blog/2008/8/3/vs-addins-revisited-declarative-button-order-and-location-wi.html)

- Aug 3, 2008

    ### [Before testing an addin - Reset Visual Studio’s previous addin knowledge](https://osherove.com/blog/2008/8/3/before-testing-an-addin-reset-visual-studios-previous-addin.html)

- Aug 2, 2008

    ### [Deadlock detectors](https://osherove.com/blog/2008/8/2/deadlock-detectors.html)

- Aug 2, 2008

    ### [Howto: Set custom Visual Studio Addin menu icons without a satellite dll](https://osherove.com/blog/2008/8/2/howto-set-custom-visual-studio-addin-menu-icons-without-a-sa.html)


---

## About the author

**Roy Osherove**: Senior Solutions Architect at AWS working on AI for production and AI-driven development; author of The Art of Unit Testing and Elastic Leadership, with about 20 years of consulting and training on unit testing, TDD, team leadership and continuous delivery.

### Sites

- [RobotPaper](https://robotpaper.ai/): This blog: AI patterns and anti-patterns, AI and coding agents, and engineering leadership.
- [osherove.com](https://osherove.com): Roy's personal site. Author of The Art of Unit Testing and Elastic Leadership; consulting and training on unit testing, TDD, team leadership and continuous delivery, plus about 20 years of blog posts.
- [The Art of Unit Testing](https://www.artofunittesting.com): The Art of Unit Testing, 3rd Edition (Manning): readable, maintainable, trustworthy unit tests, plus TDD workshops in C#, JavaScript, Java and Kotlin.
- [5whys.com](https://www.5whys.com): Roy's writing on software team leadership: self-organizing teams, surviving chaos, learning mode and the Elastic Leadership model.
- [Pipeline Driven](https://pipelinedriven.org): Continuous delivery and DevOps practices: build patterns, pipeline-friendly testing, DevOps metrics and enterprise DevOps.
- [Elastic Leadership](https://www.elasticleadership.com): Elastic Leadership, Roy's framework for software team leaders (survival, learning and self-organizing modes).

### Social

- X: https://x.com/royosherove
- LinkedIn: https://www.linkedin.com/in/osherove/

### Contact

- Contact form: https://forms.gle/jQSx5KoXvrVA1JCK7

### License

Licensed under CC BY 4.0 — reuse, quote and adapt with attribution (Roy Osherove, link to the original page). License: https://creativecommons.org/licenses/by/4.0/
