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 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.
Alternatively, you can take advantage of Clide, a more intuitive and .NET friendly API, which leverages Linq, extension methods, dependency injection for testability, etc.
Provides a managed, intuitive, modern and composable API for Visual Studio extensibility and automation. It leverages dependency injection in Visual Studio, supports unit testing of automation and extensibility code, and provides useful primitives for both consuming VS services and tools as well as providing your own.
Install from https://nuget.org/packages/Clide
If you are authoring any kind of Visual Studio tooling or automation (either from a VSIX or from a NuGet PowerShell script), Clide can make things easier, by providing an intuitive API for the solution, tool windows, option pages, etc.
High-level, composable and testable APIs for working with Visual Studio.
* Added FindProjects extension method for ISolutionNode, which is more efficient than traversing the entire solution.
* Improved support for side-by-side versioning of Clide assemblies deployed by multiple extensions
* Reworked internals to avoid depending on VS-MEF extensibility, which is problematic and may cause interference with VS composition.
* Core DI now provided by Autofac, which gives us a performance boost in addition.
* Components now don't need any [Import] or [ImportingConstructor] in order for constructor dependencies to work, even for core VS services like IServiceProvider or IVsShell, DTE, etc.
* Types that have the ComponentAttribute applied are automatically registered.
* Supports registering with a certain type (like [Export(typeof(IMyService))]): [Component(typeof(IMyService))]
* Added support for registering components as single instance (singletons) using [Component(IsSingleton = true)]
I've seen VS extensibility and automation in a number of projects I've highlighted over the years and it always kinds of makes my brain hurt. Now seeing this, I wonder if this is the VS Extensibility aspirin I've long been looking for?
Oh yeah and I love that this open source. :)