Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can a VS extension target multiple versions in regard to Microsoft.VisualStudio.* references?

A few extensions that I'm using are broken under VS2012 because at some point they were updated to work with VS2013, by changing the version of referenced libraries. At runtime an error like this can be produced:

Could not load file or assembly 'Microsoft.VisualStudio.Shell.12.0, Version=12.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.

  • I see various extensions referencing multiple versions of the same library:

    <Reference Include="Microsoft.VisualStudio.Shell.Interop" />
    <Reference Include="Microsoft.VisualStudio.Shell.Interop.8.0, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    <Reference Include="Microsoft.VisualStudio.Shell.Interop.9.0, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    
  • Others release an extension per VS version.

  • Another option, according to this article, is to dynamically load the correct version.

I'd like to help fix these extensions, but what's the proper way to tackle this issue?

like image 971
user247702 Avatar asked Sep 01 '14 13:09

user247702


Video Answer


2 Answers

So the Visual Studio reference assemblies break down into a few different categories, which you should handle differently depending upon the category:

  • Interop assemblies: these are the ones like the Interop.* assemblies you listed in your question. Each interop assembly isn't a newer version of the "same" thing, but rather an assembly that contains all the COM interfaces that were added in that version of Visual Studio. Referencing old versions is fine, just don't reference a newer one than the lowest version of Visual Studio you want to target
  • Editor assemblies, Roslyn: Anything related to the core text editor (assemblies are Microsoft.VisualStudio.Text.Data, Microsoft.VisualStudio.Text.UI, Microsoft.VisualStudio.Text.UI.Wpf, and Microsoft.VisualStudio.Editor) and Roslyn Visual Studio includes assembly redirects that redirect whatever version you're referencing to the version of VS you're actually running in. Once again, target the lowest version that you intend to support.
  • Microsoft.VisualStudio.Shell.[version]: this one confuses people a lot. How this particular assembly works is for each version of Visual Studio that ships, a new assembly name (with the version in the assembly) is made. Then, in future versions of the Visual Studio, we ship a newer version of the assembly that you target. So again, make sure you're targeting Microsoft.VisualStudio.Shell.[version] with the lowest version you intend to support.

The tricky problem here is the VSSDK project upgrader likes to upgrade your projects to newer versions. Get used to editing MSBuild files by hand to ensure it doesn't do this, or downgrade what it already did. For the final VSIX you ship to users it's often best to either build with an older version of VS to ensure it's not picking up newer stuff by accident. If you want to only use a newer version, then you'll have to find the VS binaries from the older version you wish to use and check those into your source control system to ensure the older versions are still being picked up. Test your VSIX if you go this route as it's easy to make a mistake and reference something newer by accident.

like image 89
Jason Malinowski Avatar answered Nov 10 '22 15:11

Jason Malinowski


I wrote an article discussing the various assembly versioning policies used by Visual Studio assemblies.

http://tunnelvisionlabs.github.io/vsbase/docs-master/html/edbfd3ce-43f4-4f3f-a90c-bc22bda19fae.htm

In addition, the VSSDK.* NuGet packages use dependency declarations to help you identify the version(s) of Visual Studio each extension can be used with.

The particular version of Microsoft.VisualStudio.Shell you referenced is a Versioned Assembly (per the previous article) and included in the VSSDK.Shell.12 package, with the following description:

This package provides the Visual Studio "Shell" reference assembly used by Visual Studio 2013 and newer.

To easily target both Visual Studio 2012 and Visual Studio 2013, use NuGet to manage your VS SDK dependencies, and ensure the following conditions hold:

  1. Make sure your assembly does not have a dependency on the VSSDK.IDE.12 NuGet package. This dependency means one or more assemblies referenced by your project only work with Visual Studio 2013 and newer.
  2. Make sure your assembly does not have a dependency on VSSDK.IDE.10Only, VSSDK.IDE.11Only, or VSSDK.IDE.12Only. These indicate that your package references one or more assemblies that only work with a particular version of Visual Studio.

Ideally you would only want to install VSSDK NuGet packages which include both the vs2012 and vs2013 tags.

like image 32
Sam Harwell Avatar answered Nov 10 '22 14:11

Sam Harwell