Extending Visual Studio
This article is part of the series 'Extending Visual Studio'.
This is the second in my series of articles on extending Visual Studio. In this article we're going to look into a way to extend Visual Studio that has been around for a while - addins.
We'll create a very funky addin called 'Switch'. This addin will allow us to switch between related files - C++ header and source, WinForms code and designer, XAML and code-behind and so on.
In this article we'll start with one of the simplest ways to extend Visual Studio - creating Code Snippets.
The addin created in this article, Switch, has become quite popular - you can keep up to date with the code and the project on GitHub, at github.com/dwmkerr/switch.
What is an Addin?
An add-in is a DLL that Visual Studio loads into memory to perform a task or present functionality to the user. What is most useful about an add-in, in terms of development, is that we have access to the DTE2 object. DTE2 is the top-level object in the Visual Studio Automation Model. This is a set of interfaces and objects that you can use to interact with Visual Studio.
So what can we do with DTE2? Here are some examples:
- Access and invoke the commands visual studio offers.
- Perform builds
- Go through the items in a solution
- Add controls to the user interface
- ...and much more...
Essentially with the Visual Studio Automation model, if Studio can do it, so can you.
So let's look at the brief for this add-in project. What do we want to do? First we can outline our requirements.
- Switch should add a command named 'Switch' to Visual Studio 2008 or Visual Studio 2010 that we can invoke with the mouse or keyboard.
- Switch should switch between a C or CPP source file and it's header, and vice versa.
- Switch should switch between the Code View and Design View of a C# form.
- Switch should switch between the XAML and Code Behind of a WPF/WP7/Silverlight XAML file.
- Switch should have an installer to make deployment straightforward.
We can get all of the functionality required for the first four items from a Visual Studio add-in - and we can use a standard Deployment project for the fifth item. So without further delay, let's get started. As an aside, all of the screenshots and code in this article will be based on Visual Studio 2010. The source code actually has the same add-in for 2008 as well - however the code is essentially the same (main classes are added as links in both projects, so the functional code is in fact exactly the same).
Creating the Snippet
Kick of Visual Studio 2010 and choose File > New > Project...
We'll create a new Addin project, which is in the 'Extensibility' group of 'Other Project Types'.
Now we must specify our project settings. The ones we need to be careful about are - ensure you're using C# or VB, make sure that we choose Visual Studio as the host, but not Visual Studio Macros and make sure you choose 'Yes, create a tools menu item'.
Now that we have created the project, we have a good starting point for our addin. The most key file that we have created is 'Connect.cs' - this is what is actually doing the work when the addin is loaded.
The Connect Class
The Connect class is the class that handles the integration of the addin into Visual Studio. So let's take a look at it in a bit more detail.
The constructor, here we can perform any initialization we may need to do. However, in general try and defer anything complex to one of the later functions.
This function is called to actually execute the addin command. An addin may actually add many commands to Visual Studio, this function will be used to make sure we perform the correct behaviour.
When the set of Visual Studio Addins is changed, this function will be called.
This function is called when Visual Studio is about to be closed.
This function is called when the addin is being loaded. It is in this function that we add the 'Switch' command to the Tools menu.
This function is called when the addin is being unloaded.
When the host application (Visual Studio) is fully loaded, this function is called.
Visual Studio will call this function to see if the addin should be shown, whether it should be enabled or disabled and so on.
So all together, the Connect class is not very complicated - it has to do some work to add the Switch command to the appropriate menu, but asides from that it's very basic. It has as member variables the addin instance, and
_applicationObject - this is the DTE2 class that allows us to interface with Visual Studio.
To keep things clean, we will create a new class called 'Switcher' which will perform all of the switching functionality. This class will be a singleton, so all we need to do in preparation is modify the Exec function, as below:
public void Exec(string commandName, vsCommandExecOption executeOption,
ref object varIn, ref object varOut, ref bool handled)
handled = false;
if(executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
if(commandName == "Switch.Connect.Switch")
handled = true;
This has put us into a good place. All we need to do now is create a singleton that switches the active document and we've got the core functionality we need.
The Switcher Class
Let's now create a class that'll actually take a document and attempt to switch it to a related document. We'll call this class
Switcher. I've implemented it as a singleton, it could just be a class with static methods, it's really down to personal preferences. The first thing we can do is make it 'singleton-ish' by having a private static instance, a static property to get the instance, and a private constructor to do anything that it's nice to delay:
public class Switcher
private static Switcher instance = null;
public static Switcher Instance
if (instance == null)
instance = new Switcher();
This is the basic layout for a singleton. This is not an article on the singleton pattern, I'm just using it so that from here on I don't have to bloat the code in the article with
static modifiers, which should make it clearer. Look at Martin Lapierre's excellent article on generic singletons in C# for a really good article on singletons - Generic Singleton Pattern using Reflection in C#.
The first thing the switcher will do is try and work out if the active document has a designer - and if it does try and toggle between the code and design view. Let's put some functions together to do this. The first will try and determine whether the file has a designer.
private bool DoesDocumentHaveDesigner(string path)
string designerPath = Path.Combine(Path.GetDirectoryName(path),
Path.GetFileNameWithoutExtension(path)) + ".designer.cs";
This is a slightly clunky way of checking whether a solution item has a designer - is there a file of the same name that ends in 'designer.cs'. Determining whether a document can have a designer is very hard in Studio (but not as hard as determining whether a window is a designer) so this will do the trick with the minimum amount of effort. Now we need a function to try and toggle between the code and design view.
private void TryToggleCodeDesignView(Document activeDocument)
This is the real fudge. There is no programmatic way (that I have found) to determine whether the active document is open in the designer or not. However, designer windows have the text '[Design]' at the end of the title. We can check to see if we are in a designer window, and then re-open the project item in the code view (or vice versa). This is the first thing we must note for testing and further development - in other languages this trick may not work!
These functions will let us switch between code and designer, but what about switching between cpp/h or xaml/xaml.cs files? To do this, we'll create a class called
SwitchTarget will just represent what we go From, to what we go To. If the document path ends in 'From', we'll try and find a document that ends in 'To' and open it. We can then create as many switch targets as we like - and even potentially chain them so that we can switch between three or more documents in order.
SwitchTarget class - it stores the From and To and can map a path that ends in From to one that ends in To:
public class SwitchTarget
public SwitchTarget(string from, string to)
From = from;
To = to;
public string MapPath(string path)
if (path.Length < From.Length)
return path.Substring(0, path.Length - From.Length) + To;
public string From
public string To
Now we can add a list of
SwitchTargets to the
Switcher class and set them up in the constructor. Change the constructor of
Switcher to the code below, and add the collection:
private List<SwitchTarget> switchTargets = new List<SwitchTarget>();
switchTargets.Add(new SwitchTarget("c", "h"));
switchTargets.Add(new SwitchTarget("cpp", "h"));
switchTargets.Add(new SwitchTarget("h", "c"));
switchTargets.Add(new SwitchTarget("h", "cpp"));
switchTargets.Add(new SwitchTarget("xaml", "xaml.cs"));
switchTargets.Add(new SwitchTarget("xaml.cs", "xaml"));
Now we have a way to define what we switch from, to what we switch to. With this, we can now build the final
public void Switch(DTE2 application, Document activeDocument)
List<SwitchTarget> targets = new List<SwitchTarget>();
foreach (var target in switchTargets)
foreach (var target in targets)
And that's it! The project includes a StringExtensions.cs file that includes an extension method named '
EndsWith', in case you are wondering where this function comes from! The only function that we haven't got is '
TryOpenDocument' - so here it is. Remember that there's no guarantee the switch target will exist, so we can only try to open it - we can't guarantee.
private bool TryOpenDocument(DTE2 application, string path)
foreach(Document document in application.Documents)
if(string.Compare(document.FullName, path) == 0)
if (document.Windows.Count > 0)
application.Documents.Open(path, "Text", false);
We've got the core functionality done - if you hit F5 you can run up Visual Studio and switch between related documents.
Building an Installer
An installer for an addin is very trivial - just make sure that the *.addin file doesn't have a path to the assembly, just the assembly name, then put the addin file and the assembly in the folder 'My Documents/Visual Studio 2010/Addins'. Here's a screenshot of how the MSI File System screen should look (the main project actually supports Visual Studio 2008 as well, that's why there's more folders!)
Using a Custom Icon for the Command
If you've been following the code and building your own project, you'll notice that the command has a big smiley face for an icon. While this is very jolly, we may want to use our own icon. This is a rather tricky thing to do as it turns out, so I have left this to the end.
How is the Icon set?
Take a look at the
OnConnection function of the
Connect object - the key line is below:
Command command = commands.AddNamedCommand2(_addInInstance,
"Switch between related files",
The boolean parameter set to true tells the environment that the following value (59) is the index of the visual studio icon to use. There are thousands to choose from, this article will show you how to see them all: http://msdn.microsoft.com/en-us/library/aa159658(office.11).aspx.
However, what if we don't want to use an icon from this set but our own? Here's how we do that. First, add a new resources file to the solution, named it Resources.resx and delete the associated designer file. Your 16x16 icon bitmap to the solution. If you need to have a transparent part of the icon, use the color RGB(0, 254, 0). The screenshot below shows the switch icon with the transparent special colour:
Now add the icon to the resources file, and ensure it has the name '1'. The resources code should have an entry like this:
<data name="1" type="System.Resources.ResXFileRef, System.Windows.Forms">
Version=188.8.131.52, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
Make sure the build action is set to 'no action' - we'll build the satellite assembly ourselves. The resources must be built in a satellite assembly or Visual Studio won't pick up on them. We can build the satellite with the commands below:
"C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\resgen.exe" Resources.resx
"C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\al.exe" /t:lib
/embed:Resources.resources /culture:en-US /out:Switch.Resources.dll
Now when we deploy the Switch assembly - we must make sure the Switch.resources.dll is in a subfolder named 'en-US' or Visual Studio won't pick up on it! There are batch files in the download to perform these commands.
The final thing to do is add the .vscontent and .snippet file into a new *.zip file and rename it from zip to vsi. This creates a VSI installer - double click on it and you get the below:
Now that we have a Switch add-in, we can add it anywhere to the Visual Studio UI and bind a keyboard command to it. In my setup I have Switch super-accessible at the right of the main menu and bind it to Ctrl+Alt+S. Now whether I'm in C++ code, XAML or a WinForms project I can flick between related files.
There are loads of potential improvements to the project - making switching configurable, fixing the fudges that won't work in other languages and so on - but a basic project like this is a great way to get started with Visual Studio Extensions.
I hope you have enjoyed this article and found it useful, keep up to date with my writing by following my blog at www.dwmkerr.com - as always any suggestions are welcome.
- 11/06/2013 - Updated the article with the 2.0 version of the Setup program, which supports new features.
- 26/08/2012 - Updated the Switch Setup download with support for Visual Studio 2012.