http://blogs.clariusconsulting.net/kzu

Daniel Cazzulino's Blog

Go Back to
kzu′s Latest post

High level overview of Visual Studio Extensibility APIs

If your head is dizzy with the myriad VS services and APIs, from EnvDTE to Shell.Interop, this should clarify a couple things.

First a bit of background:

APIs on EnvDTE (DTE for short, since that’s the entry point service you request from the environment) was originally an API intended to be used by macros. It’s also called the automation API. Most of the time, this is a simplified API that is easier to work with, but which doesn’t expose 100% of what VS is capable of doing. It’s also kind of the “rookie” way of doing VS extensibility (VSX for short), since most hardcore VSX devs sooner or later realize that they need to make the leap to the “serious” APIs.

The “real” VSX APIs virtually always start with IVs, make heavy use of uint, ref/out parameters and HResults. These are the APIs that have been evolving for years and years, and there is a lot of COM baggage. IVsHierarchy is a pretty representative example. But there’s hope, since most of the newer capabilities of the IDE are exposed with much more modern and .NET-friendly APIs, such as IVsExtensionManager.

Solution Traversal

Solution traversal is such a core activity for any VS extension that you almost always need to do it sooner or later. As you probably guessed, there are two main ways: DTE/Automation way, and the IVs* way.

One key thing to understand is that the automation API is an *optional* API that project types can decide to support. There’s no guarantee that any part of the automation APIs will work for a particular project. This is what may cause an extension to fail for example in a solution with a VC++ project and not with “regular” C#/VB projects.

 

I’d always go for the IVs* way always, since it’s more reliable, and works with projects that may not expose automation API for their custom project types. You can always get at the information the DTE API exposes by using the IVs* APIs, but it’s generally quite a bit more work.

 

Too Painful?

Alternatively, you can take advantage of Clide, a more intuitive and .NET friendly API, which leverages Linq, extension methods, dependency injection for testability, etc.

For example, after doing

install-package Clide

on your Visual Studio extension, you can write code like this to retrieve the display name of all projects in the solution:

var projects = DevEnv.Get(serviceProvider)
    .SolutionExplorer()
    .Solution
    .Traverse()
    .OfType<IProjectNode>()
    .Select(project => project.DisplayName)
    .ToList();

(this requires two using statements: Clide and Clide.Solution).

You can do things like show the solution explorer, save the solution, subscribe to solution and project events, and much more.

 

Clide is open source software provided by Clarius Labs. And being a NuGet package, its documentation is available at NuDoq, of course ;)

Comments

9 Comments

  1. Very nice Kzu! I want to try Clide it and play a little.

  2. [...] High level overview of Visual Studio Extensibility APIs – Daniel Cazzulino discusses some fo the pain points of interacting with the Visual Studio Extensibility API, and shares a look at Clide a helper library which deals with working with the solution. [...]

  3. Genial Daniel !!!

    Descargando

  4. Any links to documentation?

  5. Being a nuget, the documentation should be in the NuDoq site, of course, at http://www.nudoq.org/#!/Projects/Clide

    It seems we have a missing SDK on the generator server that we need to fix first :(

  6. How do you define the serviceProvider variable?

  7. Nice Daniel, Besides the documentation, are there any tutorial and/or examples available somewhere?

  8. I’m sorry. I wasn’t clear enough. I ment about Clide, sorry.