Changes to Visual Studio “15” Setup

We’ve listened to feedback over the years, and while each new release brought changes to the setup experience of Visual Studio and related products, none have been more significant than what we’re doing for Visual Studio “15”.

New setup engine

With Visual Studio supporting so many platforms and toolkits, one of the goals for Visual Studio “15” is to provide choice and install just what you need. To make it easier for our partners to author component packages for Visual Studio while making sure you get all the required components, an underlying engine needs to provide granularity and cohesion with dependencies. Existing package managers like NuGet and NPM provided much of the inspiration, and we bolstered dependency resolution with additional flexibility. This means that whatever workloads and components you select, and whatever product languages you choose to install, you should get everything you need and only what you need.

Another goal is to install faster. Along with a ground-up rewrite of the setup engine, we also extended VSIX packages to install the core product and many of its components while still supporting platform-specific functionality we had with Windows Installer packages like creating file associations, shortcuts, and NGEN’ing assemblies. Now we can install Visual Studio “15” faster and with better isolation. Many legacy and some updated components continue to ship Windows Installer packages or black box executables, but this work in progress has already seen a lot of migration to the new format and more will follow. These mostly-extracted installations are isolated and can be updated with less interaction with other products or editions.

Product instances

To support a model with lightweight and isolated installations that do not interfere with other products and editions, we needed a way for all partners to query for products that match some set of requirements, like finding the latest Visual Studio “15” that have C++ compilers installed. Registry queries wouldn’t provide the flexibility required in many scenarios we discussed with partners. So we created the concept of “instances” – basically the root folder of an installation and other information about what was installed in that folder (and outside that folder, for legacy packages). Each instance also has its own private registry so they can be configured independently.

The COM server DLLs that implement this functionality will be installed by the setup engine and available on any systems with at least one instance of a product installed. If CoCreateInstance returns REGDB_E_CLASSNOTREG (0x80040154) or a COMException is thrown in managed code with the same HRESULT, it’s a good bet no instances are installed.

While we are exploring other ways to provide discovery, we recently published a set of NuGet packages for native and managed code for VS15:

You can query all instances installed by the new setup engine, or get an instance for a specified path or the current process path. Using the information provided (and we will be exposing more as we collect feedback), you can determine what workloads and components are installed, and resolve paths to compilers and other tools.

If, for example, you wanted to check if some component package was installed before attempting to light up a dependent feature in the current instance, you could do something like the following:

We will be publishing more about the updated VSIX extension format, how it supports prior releases, and how to depend on workloads and components for VS15 in future posts. For updated samples, please see https://github.com/microsoft/vs-setup-samples.

It’s great to see a set of libraries that can help us to find VS installations, but the license attached to these Nuget packages is a restricted evaluation license that does not permit distribution of the libraries with an application.

Probably this is by mistake, but it means that no one can distribute any VS packages that use the libraries without being in breach of the agreement. Can this please be fixed?

This is our standard pre-release license and we will be changing it soon; however, there’s no need to redistribute the binaries. Setup will register them, and if you try to CoCreate and get REGDB_E_CLASSNOTREG you should treat that as no instances installed. The RCW is also embeddable (default for managed project for at least a couple releases) so no managed assemblies need to be shipped.

Could you please specify what exactly “multiple installed instances” mean? I’ve installed VS 2017 RC and I can only install Community, Professional and Enterprise. This means a limited set of three instances. Will it be possible to install e.g. 4 instances of Community edition, each with a different workload set?

Capabilities for the pre-release are limited as some functionality both in setup and in the product itself to support those capabilities are being finalized. More information will be available in the future. Also keep in mind that the installer can install more than just VS. Each separate install is an instance, and instances can have similar or different functionality, hence the need for the query API to allow enumeration of workloads and components installed therein.

I just spent the entire day looking into the situation and it appears like it’s is going to be a (very) painful experience getting it to work in the installation program for my VS extension (and those of other extension developers). How do I simply detect which versions of VS2017 (Community, Professional or Enterprise) are installed for instance, if any (in the installation program for my own product). I looked at the NuGet package you posted and it’s not clear, even after studying the interfaces. Am I supposed to compare the product name to a string like “Microsoft.VisualStudio.Product.Community” for instance? There’s no official documentation that I can find to clarify things. Moreover, it has to be callable from an MSI program as well, including an MSI custom action. Am I supposed to embed the NuGet DLL into my “.msi” file and call it somehow (since I need to detect which versions of VS are installed before my own product is installed, so the NuGet DLL won’t be on the customer’s machine yet). If so then what a pain (seriously!). The installation tools that deal with this aren’t equipped for it, including your your own installation technology (long story). Moreover, there are other registry entries that developers rely on, such as those seen under HKEY_LOCAL_MACHINE\SOFTWARE\[Wow6432Node]\Microsoft\VisualStudio\14.0\Setup\vs (a Visual Studio 2015 example but the equivalent key applies to earlier versions as well). I rely on the “EnvironmentDirectory” value under that key for instance so where is it in VS2017? The registry entries in previous versions were orders of magnitude easier. Unless I’m missing something a lot of developers are going to be P.O.’d about the situation. How about some official guidance? The RC version of VS2017 is out now (suitable for production according to your docs), so where’s the documentation for detecting it and obtaining info on the various directories some of us need to access (and why hasn’t the following link been updated yet: https://msdn.microsoft.com/en-us/library/bb164659.aspx)

We are working on MSDN documentation and the license will change, but there is no need to – and, in fact, I recommend you don’t – redistribute the DLLs. They are COM servers, and will be installed and registered with the first instance installed. The GetSetupConfiguration entry point was meant for redistributing originally, but is now more used for testing and remains. But you should CoCreate the SetupConfiguration class and QI what you need, which the samples provide and the Setup.Configuration.h header documents (the MSDN documentation will be primarily that, as it is with nearly all Framework documentation. The NuGet packages are merely for building applications against those libraries, as NuGet packages always are. We do not install the NuGet packages during setup. They are meant as development packagers only.

Yes, product searches will require a comparison of longer strings as you noted, but these are only namespace-qualified versions of what you did before. With the old registry keys, you still had to use “Enterprise” and such. Those values are being documented as part of the VS SDK.

Registry was not used because of the complexity and amount of data we store about each instance. Putting that much information in the registry slows down Windows. The product as a whole has removed almost all registry, in fact. The APIs are to abstract the storage mechanism that has and likely will change again without affecting the APIs.

I’ve been on the VS Extensions forum for the past 2 weeks trying to get answers or trying to find a solution to an existing deployment installer. I’m in charge of a VS Package extension which was registering through a custom app that writes to the different VS registries, and using the Visual Studio installation path registry keys to determine which devenv.exe /setup should be run to register the private code base assemblies. This strategy works for customers on VS 2005 to VS 20015.

However, it looks like that is no longer possible with VS 2017. Any advice on how to proceed? Seems like the best bet is to port the old VS Package code (again, just the code only) to a new VS 2017 extension project, and try to figure out a deployment strategy from there.

Rather than checking for registry you’d just call into the query API to enumerate instances – this includes different versions of VS as we release them. You could still use registry for older versions, but if you were to abstract away discovery everything else should just work.

Not currently, no. The properties are available in 3.11 and a PR has been out for 4x but not yet merged. Changes to support VsixPackage may come later. Ultimately, the problem is that a VSIX can now depend on a feature that may install and MSI, and you can’t install MSIs from within a custom action while installing MSIs. MSIs cannot install concurrently.

I can see that to install/uninstall any VSIX to VS2017, a dialog appears telling that some processes prevent the installation. These are any version devenv.exe process and also ServiceHub… background processes. The suggestion in the article is:

“Wait for the processes to shut down, or manually end the tasks.”

This is VS2017 RC not RTM. My opinion is that if this behavior is still there in RTM, we (both MS and extension partners) will face a *** tsunami of complain from users ***. Not only this is a major regression from previous VS version but background… process persists for like a minute or more. Users just don’t have the time to neither wait processes end up, nor the time to open a cmd task and type “taskill /PID 1234” stuff.

Thanks for the feedback. The changes a required because extensions may update files which are in use and if we do not block, the install could fail part way through and leave the user with a corrupted partially-installed state.

We have made improvements to the speed at which some tasks shutdown (servicehub) and we have also added the ability to end the tasks directly from the vsixinstaller UI.

From VS2010 to VS2015, VS didn’t have this limitation, it is very convenient, I studied in depth how it behave and it is pretty smart.

>>We have made improvements to the speed at which some tasks shutdown (servicehub) and we have also added the ability to end the tasks directly from the vsixinstaller UI.

This is indeed way better than the actual RC behavior.

However Installing / Uninstalling VSIXs is a common task in the .NET developer daily routine, and each time (s)he’ll have to close all its VS instances and then re-open them. IMHO this is an important regression to put in balance with the VS startup performance improvement.

Michael, while I accept that there have been some improvements made, I still agree with Patrick that this is a major regression from previous VS versions.

As an extension developer I have to protest at having to close down ALL of my open instances of VS, INCLUDING VS 2015, just to install a single extension that I want to try out, or update if it’s my own extension. I often have up to 3 instances of VS 2015 open, plus maybe one or more instances of VS 2017 open. Even if I’m only installing a VS 2015 extension to VS 2015, I have to shut down ALL 5-7 instances that I have open, before I can do that! I’m sorry, but that is NOT acceptable behavior.

For installing a single instance of any extension (2015 or 2017) to VS 2015, or to a single instance of 2017, I want the install/restart experience that we’ve always had before. And before you bring up the possibility of there being multiple instances of VS 2017 installed, Most of us will probably only ever want to install a particular extension to a particular instance of VS 2017, not to all of them. What’s the point of having multiple installations with potentially different workloads if every extension that we install is installed to all of the installed VS 2017 instances, even if they don’t apply to that workload. What’s going to happen if the extension demands features that weren’t install to one/some of the different workload installations? Is the user going to be forced to install features that don’t apply to that workload?

Like we always have, let us select which VS versions/instances that we want to install an extension to (from a list of all installed VS versions/instances), and:

a) if only VS 2015 (or earlier) is selected, or a single instance of VS 2017 is selected (or one of each), give us the existing install/restart experience

b) if multiple instance of VS 2017 are selected, ONLY THEN give us this new inconvenient, time-wasting, frustrating experience that you have planned for us.

I also concur that you are going to receive complaints from users in DROVES, people like Patrick and I are merely riding the tip of the wave.

If you install an extension via the Extension Manager, that extension is only installed into that instance. If you download a VSIX and double-click it (or otherwise open it with VSIXInstaller.exe), you are prompted not only into which versions of Visual Studio you want to install, but also what instances.

We are currently exploring different solutions with the WiX developer community – of which I’ve long been a part – how to enable that scenario for MSI-installed VSIX since prompting during silent installs of MSIs is ill-advised and will break automation.

We are aware of the feedback regarding shutting down VS and discussing options.

I’m just now looking at VS2017 for IsWiX (project templates and VS addin for WiX). I read your WIP but I’m not using burn. I’m just a simple MSI that was using the NetFx property references to use CopyFile elements to put my ZIPs in the right places and call devenv /setup. With this whole multiple instance story it would be interesting to see the WIP could include something along the lines of emitting temp records to the DuplicateFiles tables based on what the custom action found and then use MSI to disperse the files where needed and call the various devenv setups.

The WIP isn’t specific to Burn. It details the changes to VsixPackage, which schedules custom actions. It only needs to find VSIXInstaller.exe, which will handle installing to multiple instances. You could accomplish the same thing if you’re not using VsixPackage from the WixVSExtension.

I’ve knocked something together from the example code, its not pretty but it works https://github.com/alanbirtles/GetMSVCPath just run “GetMSVCPath 15” to get the root directory of a 2017 instance with VC installed.

Just had a miserable time trying to install Visual Studio 15 Community on a Windows 7 X64. The whole process took a VERY long time (I have a reasonably fast fibre connection). In fact it took so long I went to bed to let the thing install overnight.

On start up, I got one of the most annoying screens ever when I was told i had to verify my credentials. I then got into a loop when I was advised that “Cookies must be enabled” (they are). Enough of this garbage I am now in the process of uninstalling Visual Studio 15 and, surprise, surprise that is taking forever as well.

I’m not interested as to why this has happened – I don’t have the time or the inclination – but this experience for me was a throwback to dark days of installing MIcrosoft “upgrades” that took forever with a good chance of the Blue Screen of Death at the end of it. I think Microsoft are displaying too much of the same disconnect with their clients that politicians show towards the people at large. They speak to the wrong people as to what the client wants. From 2005 on, I found Visual Studio quite straightforward to install but, as usual, Microsoft just cannot leave well alone.

Sorry you’re running into problems. Telemetry and customer studies show it to be faster on average than past releases, but a full install is much bigger with more third-party value included than ever before, which is why we cut down the default install and added on-demand feature installation. If you’re experiencing problems like this, we can only improve it if we have more data to diagnose.

For PowerShell, use the VSSetup cmdlets which are easy to obtain and redistributable: https://github.com/Microsoft/vssetup.powershell. We didn’t implement IDispatch for automation support because a PowerShell module was going to be made available (the ones I mentioned) and the RCW is available for managed code (what the PowerShell module uses).

How would implementing IDispatch help node-gyp? They’d need to code against it anyway, which they can just as easily do against IUnknown (easier, in fact: C++ against IDispatch is a hassle).

I too had a simple set of PowerShell scripts/cmdlets that setup my environment (similar to the ones found in PSCX) and they relied on the and they relied on VSXXXCOMNTOOLS to work. Now that’s gone, and there’s no registry to tap into.

Currently I’m trying to cook up scripts that calculate the delta in the environment in a bare shell and one that invoked vcvars64.bat so I can hand the changes over to the configuration json of CMake Tools of Visual Studio Code, so that I need not joke around with ONLY launching VS Code from a developer Cmd Prompt (it has it’s downside, predominantly the lengthy execution of vcvars64.bat which will add to every VS Code launch, even when I just want to edit text files.

This addon used to have automatic environment detection, but now placed focus elsewhere, because the new system is very hard to detect from the typescript code of the addon. I do not envy the guys. It all results in second grade command-line experience. I understand there was need for a change, it’s just surprising there’s still no solution since Preview 1. Or did I miss something?

If you only have one instance, you could define the environment variable with the value indicating the path you want. But I don’t understand the rest of your solution. Could you clarify? We did work with CMake to provide a solution for them, so using more recent versions of CMake should be able to compile to a valid a VS solution.

CMake Error at CMakeLists.txt:5 (project):
No CMAKE_CXX_COMPILER could be found.

— Configuring incomplete, errors occurred!
See also “C:/Users/Matty/Build/CMake_example/CMakeFiles/CMakeOutput.log”.
See also “C:/Users/Matty/Build/CMake_example/CMakeFiles/CMakeError.log”.

This is not exactly working the way it should. All other VS Generators detect the corresponding installation, and I guess this should one too. Well, my instance is installed under C:\Kellekek\Microsoft\Visual Studio\15RC and it most certainly does not find it. Will give 3.8.0 a spin.

What I’m talking about is however using MSVC without the MSBuild based generator. Ninja if I want speed, or even NMake if I’m making slides and I want the output to align with GNU Make as much as possible. All these work from a Dev Cmd Prompt only. And this is the snippet of VS Code configuration .json:

This is what I have to populate with the changes brought about by invoking vcvars64.bat if I don’t want to launch my VS Code always from a dev prompt, but have the IDE setup the correct environment, so the internal calls to CMake actually find the compiler (even when not using the VS generator, which blows up the output console. I have never been able to reproduce the output as seen inside a real Visual Studio when I call MSBuild from the command line).

Our generators today are installed as part of a bigger Windows Installer package, all Visual Studio registration entries are written via Windows Installer. Looks like we would have to switch to VSIX packages, right?

ENV access is something all platforms have (COM isn’t), and like I said before the installer is an `Electron` app, and VS uses `node.js` extensively so I think it’s you responsibility to assist us in getting `Electron`, `Chromium`, and `node.js` to easily compile on VS2017

Is there a way to detect if a VS Package is already installed on any version of VS 2017 IDE…? I used VSSetup API’s for it, without much luck. VS Setup API’s gives me the versions / workloads of VS 2017 installed, but not the extensions / packages installed on those IDEs

I am working on Custom installer for VS Package. This custom installer is nothing but a cs win form application embedding the .vsix file. The idea is to provide developers UI options to install / install per machine (for all users on a machine) / uninstall the package by clicking on setup.exe. The package supports VS 2012 through to VS 2017.

Uninstall option in seup.exe is enabled only when setup.exe detects if the package is already installed on user’s machine. This detection works by detecting all versions of available Visual Studio IDEs, and then dynamically loading Microsoft.VisualStudio.ExtensionManager.dll of corresponding versions, and then searching for IInstalledExtension by name / guid.

This was working fine until VS 2012 through VS 2015. However, with VS 2017, it fails to find / load v 15.0 of dll Microsoft.VisualStudio.ExtensionManager.dll. Apparently, with VS 2017 installation, this dll is not saved in the gac.

I just wanted to check how to make this detection work in VS 2017 as well. I could not find Microsoft.VisualStudio.ExtensionManager.dll on my system which have VS 2017 professional installed. Has this dll / interface changed / replaced in VS 2017?

Or if there is any other better way to detect if an extension is already installed.

The query APIs do enumerate all packages – workloads, components, and all installable packages (EXEs, MSIs, MSUs, and VSIXes) that are installed for each instance. Enumerate instances to enumerate their packages and you have what you want. But note that VSIX extensions – per-user extensions, specifically – are not installed, handled, or detected with the new setup engine. Only per-machine VSIX extensions are via VSIXInstaller.exe.

No, VS is not in the GAC. As part of multi-instancing, little to nothing can remain in the GAC.

I just confirmed – If extension is installed per machine, Setup API’s detect it – as you mentioned. Thanks 🙂
That narrows down my research to detect if an extension is already installed per user. Not sure if there is a way around it.

In regard to GAC – I agree that VS 2017 dll’s won’t be in GAC now since multiple flavors can be installed on the same machine. However, I could not find Microsoft.VisualStudio.ExtensionManager.dll even in VS 2017 pro installation folder as well “C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional”
Has this dll been replaced in VS 2017 onwards? If yes, Can you please point me to the dll which provides similar classes / interfaces as Microsoft.VisualStudio.ExtensionManager.dll (and it’s documentation, if possible)?

I know what to do once I have the correct instance, my problem is finding the right instance. So basically, there’s no way to find out with the setup query API what packages are in EXP? Please consider this an enhancement request, doing this through extensibility would be a major pain, as each DTE object creation may take several seconds.