Visual Studio extensions and version ranges demystified

Mads Kristensen

Extension authors use visual Studio version ranges to specify what versions of Visual Studio their extensions support. A version range looks like this [14.0, 17.0) and specifies the minimum and maximum version of Visual Studio as well as if the edges are included or excluded. The syntax with mismatching braces may initially seem a bit odd and what exactly do those numbers refer to? Let’s unravel the mystery of the Visual Studio version ranges.

Snippet of a .vsixmanifest file

Let’s start by separating the version of Visual Studio from its name which can be a bit confusing. The 10th version of Visual Studio was released in the year 2010 and was given the name Visual Studio 2010. The fact that version 10.0 of Visual Studio was released in 2010 was coincidental, and made it seem like the version number followed the year of its release and therefore its name. Here’s a list of versions and names to illustrate how coincidental it was:

Version Name
8.0 Visual Studio 2005
9.0 Visual Studio 2008
10.0 Visual Studio 2010
11.0 Visual Studio 2012
12.0 Visual Studio 2013
14.0 Visual Studio 2015
15.0 Visual Studio 2017
16.0 Visual Studio 2019


If Visual Studio continues to follow a release cadence of roughly every 2 years, then there will never again be a version that matches its name. Version 113.0 in the year 2213 will be the closest match.

You may be wondering why version 13.0 was skipped or attribute it to being an unlucky number in some cultures. That’s what I always thought, but then I started asking around and it turns out I was wrong. The real reason for skipping 13.0 was the believe that it would be confused with Visual Studio 2013 which was the current latest version at the time. Whether or not it made things less confusing in the end is up to you to decide.

Version ranges

In an extension that supports version 14.0, 15.0 and 16.0 of Visual Studio, express the version range like this [14.0, 17.0). Let’s break it down into its subparts.

It starts with a square bracket meaning edge inclusive which is then followed by 14.0. Let’s call this the from-part of the version range. You can read it like from and including version 14.0.

The last part is called the to-part and consists of the version number 17.0 followed by a parenthesis. A parenthesis means edge exclusive and will therefore not include the 17.0 version number. It can be read like up to, but not including version 17.0.

The entire version range [14.0, 17.0) therefore means from, and including version 14.0 – up to, but not including version 17.0. This version range syntax was introduced in Visual Studio 2015 (version 14.0).

Updates and minor versions

When an update to Visual Studio 2017 is shipped, it maintains its major and minor version, but the build and revision numbers change.

Version number breakdown

For instance, the full version of Visual Studio 2017 version 15.1 was 15.0.26403.0. Get the version numbers from this full list of Visual Studio versions and replace the minor version with 0 if you need to use it in an extension’s version range.

An extension can use an API introduced in version 15.1 but should make sure it can’t be installed on older versions to avoid runtime errors. To do that, the version range must reflect the build number of version 15.1 and could look like [15.0.26403, 17.0).

Visual Studio 2019

Why not just write 15.1 instead of 15.0.26403? In Visual Studio 2017 and earlier, this was due to an implementation detail and we therefore had to keep a 0 as the minor version and write out the long build number. In Visual Studio 2019 we can finally start using the minor version and forget about the build number. As of this writing, the are no updates released for Visual Studio 2019, but we will be able to write version ranges like [16.1, 17.0).

Let’s imagine that I wrote an extension with a feature that users have been asking the Visual Studio team to build into the official product. Finally, they release the feature as part of an update to Visual Studio 2019. Now I must make sure my extension cannot be installed in that version to avoid the two similar features from colliding. To do that, I would update the version range to be something like [14.0, 16.1) to express that from version 16.1 and beyond the extension isn’t supported.

Since minor version numbers are supported in version ranges in Visual Studio 2019, it means that the old syntax for specifying versions should no longer be used. The old syntax was one that didn’t have both a from and a to-part and was a simple version string like 16.0. That syntax is now interpreted as only version 16.0 by Visual Studio 2019 and doesn’t include any future updates such as 16.1.

To correctly specify a version range supporting version 16.0 including all its updates, the version range to use is [16.0, 17.0).


What if you want to specify that an extension should be supported by version 14.0 and all version of Visual Studio that will ever be released after that? Express that by omitting the to-part like [14.0,) which is known as an open-ended version range. However, we strongly discourage using open-ended versioning since it is considered a bad practice. In fact, soon you won’t be able to upload extensions with open-ended version ranges to the Marketplace.

There is no way of knowing that an extension will work in all future versions of Visual Studio. It probably won’t and will eventually cause a runtime error in that future version. Where open-ended version ranges are useful is when specifying dependencies and prerequisites. If my extension supports [15.0, 17.0) and has a dependency on a component that exist in all versions, then it makes good sense to write something like this in the .vsixmanifest file:

<Prerequisite Id="Microsoft.VisualStudio.Component.CoreEditor" Version="[15.0,)" />

What version to support

In a perfect world, an extension would only support the very latest release of Visual Studio to take advantage of the latest and greatest APIs. Unfortunately, not all Visual Studio users update to the latest version as soon as it is released. It is also easier to code, test and maintain extensions targeting as few versions of Visual Studio as possible.

So how many versions back does it make sense to support? What is the right balance of ease of coding and reaching as many potential users as possible?

To answer that question, we need to know the distribution of extension users using each version of Visual Studio. Today, over 95% of all extension users are on Visual Studio 2015 (14.0) or newer. So, if I were to write an extension today, I would target [14.0, 17.0).

I hope this helped clear up how the versioning works. If not, let me know in the comments.


Discussion is closed. Login to edit/delete existing comments.

  • Steve Cadwallader 0

    This is helpful, thank you!  I really appreciate how there is a lot more information to be found as an extension author these days compared to the VS2005 days. 🙂

  • Andrey Minakov 0

    Mads, Thanks for the info, but I have this error if I do all the actions from the post:
    It’s not possible to install because there is no following links: Microsoft.VisualStudio.Component.CoreEditor.
    The updated extension.vsixmanifest is:
    <?xml version=”1.0″ encoding=”utf-8″?><PackageManifest Version=”2.0.0″ xmlns=”″>  <Metadata>    <Identity Id=”PowerQuerySDK.Microsoft.30831070-f420-4649-a031-6f679996b182″ Version=”″ Language=”en-US” Publisher=”Microsoft” />    <DisplayName>Power Query SDK</DisplayName>    <Description xml:space=”preserve”>A Power Query language service for Visual Studio</Description>    <License>Microsoft Power Query SDK – Pre-Release or Evaluation Use Terms.rtf</License>    <Icon>dataconnector_128.png</Icon>    <PreviewImage>EATIcon.ico</PreviewImage>  </Metadata>  <Installation>    <InstallationTarget Id=”Microsoft.VisualStudio.Community” Version=”[14.0,17.0)” />    <InstallationTarget Version=”[14.0,17.0)” Id=”Microsoft.VisualStudio.Pro” />    <InstallationTarget Version=”[14.0,17.0)” Id=”Microsoft.VisualStudio.Enterprise” />  </Installation>  <Dependencies>    <Dependency Id=”Microsoft.Framework.NDP” DisplayName=”Microsoft .NET Framework” Version=”[4.5,)” />  </Dependencies>  <Assets>    <Asset Type=”Microsoft.VisualStudio.ProjectTemplate” Path=”ProjectTemplates” />    <Asset Type=”Microsoft.VisualStudio.ItemTemplate” Path=”ProjectTemplates” />    <Asset Type=”Microsoft.VisualStudio.VsPackage” Path=”Dependencies\Microsoft.Mashup.Tools.VisualStudio.pkgdef” />    <Asset Type=”Microsoft.VisualStudio.MefComponent” Path=”Dependencies\Microsoft.Mashup.Tools.VisualStudio.dll” />  </Assets>  <Prerequisites>    <Prerequisite Id=”Microsoft.VisualStudio.Component.CoreEditor” Version=”[15.0,)” DisplayName=”Visual Studio core editor” />  </Prerequisites></PackageManifest>
    Please could you suggest what may be the problem?

  • Athanasios Ioannidis 0

    Wouldn’t it be better (as long as it is feasible) if VS extensions where depended on features that should be present in VS instead of being depended on VS versions?So extension developers would declare that Extentions A depends on the presence of Feature A, Feature B and Feature C, and each VS version would declare that it provides Features A, B, C, D … etc.

    • Mads KristensenMicrosoft employee 0

      It would be nice if it was that simple, but unfortunately it isn’t. That’s because the APIs keep evolving with each version of Visual Studio, so it’s important to specify which version you are depending on. You might use a new API that is only available in 16.0. If that extension is run in 15.0 then you are going to get exceptions that could lead to crashes or other bad things.

  • Pete Schieck 0

    Always thorough, Mads.  Thanks.

    • Mads KristensenMicrosoft employee 0

      That is a great question. One and it deserves its own blog post, because that is actually not easy to answer in a comment. The list of values are changing with each version of Visual Studio – some are added and some removed. I’ll add it to my blogging backlog

  • Andrey Minakov 0

    I found my problem I described earlier in comments here. It worth to mention that you shoud check file catalog.json inside the extension installation file, in addition to extension.vsixmanifest.There was mention of CoreEditor with the old version numbers in the extension, so I could not install extension until I changed file catalog.json appropriately.

    • Mads KristensenMicrosoft employee 0

      I’m glad you solved it. Yes, catalog.json needs to be updated as well if you do a upgrade by directly modifying the .vsix container files.

  • Alexander Ovchinnikov 0

    > The real reason for skipping 13.0 was the believe that it would be confused with Visual Studio 2013 which was the current latest version at the time.
    I don’t really think it was the reason. There was Visual Studio 2012 and right after it VS2013 version 12.0. You could say that version 13.0 was later and they took into account some problems with 12.0, but then there was Visual Studio 2015 and right after it VS2017 version 15.0. So I don’t think that exactly Visual Studio 2013 was the one and the only not to be confused with the next version number.

    • Mads KristensenMicrosoft employee 0

      I asked a person who was in the meeting when it was decided.

    • Yann Duran 0

      I thought the exact same thing as you @alexander ovchinnikov

  • Patrick Smacchia 0

    Thanks for all the details.  Will dte.Version remain or can we expect 16.1 16.2 … ?  With VS 2017 it is still even for 15.9.3 for example

    • Mads KristensenMicrosoft employee 0

      The EnvDTE.Version property will report only the major version (“16.0”) regardless of any updates installed – just like with previous versions.

  • Patrick Smacchia 0

    Can we expect some 16.1, 16.2 … in the context of registry keys like HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\16.0 (or any regkey like HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DevDiv\vs\Servicing\16.0)  

    • Mads KristensenMicrosoft employee 0

      Registry keys will stay 16.0. However, with the move to the private registry hives (privateregistry.bin), user should no longer try to access the non-private Visual Studio registry keys directly since they are implementation details, can be changed without notice, and/or might be removed. 

      • Patrick Smacchia 0

        Thanks Mads, still quite useful to access the private registry hives for info like themeId or MRU VS files paths.

  • Patrick Smacchia 0

    Can we expect some 16.1, 16.2 … in the context of folders like  C:\Users\(user)\AppData\Local\Microsoft\VisualStudio\16.0 
    or any path under C:\Program Files (x86)\Microsoft Visual Studio that might contain 16.0 like
    C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\MSBuild\Microsoft\NuGet\16.0
    C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0
    C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\Microsoft\NuGet\15.0
    C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\Extensions\Microsoft\Modeling\15.0

  • Patrick Smacchia 0

    Can we expect some 16.1, 16.2 … in the context of VSIXInstaller.exe /skuVersion:16.0 …   

    • Mads KristensenMicrosoft employee 0

      No, the /skuVersion will remain 16.0 for extensions targeting 16.0

  • Patrick Smacchia 0

    Can we expect some 16.1, 16.2 … in the context of VS dll names like Microsoft.VisualStudio.Debugger.Interop.16.0.dll  System.Drawing.VisualStudio.15.0.dll

    • Mads KristensenMicrosoft employee 0

      We usually only rev the version numbers in the file names once per major release otherwise references are broken. At this time I don’t know of any reason we’d need to rev the version in the file name until the next major VS release.

  • Patrick Smacchia 0

    Can we expect some 16.1, 16.2 … in the context of VS solution file format like 16.0.28721.148 in
    Microsoft Visual Studio Solution File, Format Version 12.00# Visual Studio Version 16VisualStudioVersion = 16.0.28721.148

  • Hristo Hristov 0

    I followed your articles to update the
    I build it and installed it. My CMake project using Clang worked but unfortunately the LLVM toolchain didn’t appear in the MSBuild project property parges. I am unable to figure out from the documentation about adding custom toolchains if anything has been changed.

Feedback usabilla icon