Thoughts about setup and deployment issues, WiX, XNA, the .NET Framework and Visual Studio
All postings are provided AS IS with no warranties, and confer no rights. Additionally, views expressed herein are my own and not those of my employer, Microsoft.
Hey all, I was talking to someone earlier this week about ways to detect whether or not the .NET Framework SDK is installed on a user's machine. They had seen my blog entry about detecting the .NET Framework redist and were curious about whether or not a similar method exists for the SDK. As I was looking into it I stumbled upon a type of detection strategy that Visual Studio and the .NET Framework SDK use internally in their MSIs that I really wanted to explain in more detail because I haven't seen other setups do this or even use this term (plus now I can write a separate post about detecting the SDK and refer to this article for more details about one of the methods).
Before I start I wanted to define a couple of terms I'm going to use later on:
The various editions of Visual Studio (such as Pro, Enterprise Developer, Enterprise Architect, etc) and the .NET Framework SDK ship many common components that can be installed to directories that the user can change in setup UI. For example - the core IDE bits are the same for all editions of Visual Studio (within the 2002 version family and 2003 version family respectively of course). Also, you can install the .NET Framework SDK tools, samples, etc by using the standalone SDK setup.exe or by choosing the .NET Framework SDK items in the Visual Studio setup selection tree. You are allowed to install any edition of Visual Studio and/or the .NET Framework SDK on the same machine, in any order, with uninstalls mixed in also.
In these multi-edition scenarios, Visual Studio and .NET Framework SDK setup do some internal detection to determine whether or not any of the common components are already installed on the user's machine. If they are, setup detects what path they are installed to, and automatically changes the install path in the setup UI for the feature(s) that contain the common component(s) to match the ones that were previously installed, and also prevents the user from changing these paths by graying out the browse button or via some other means.
We use the term vertical integration to encompass this process of performing detection, updating paths if necessary and blocking future changes to these paths in setup UI. Side note - I don't know for sure but it appears that we may have invented this term for this functionality on the VS setup team, I did some web searches and couldn't find any setup-related uses of this term (everything that came up for me was banking or financial analysis stuff).
Behind the scenes, vertical integration is implemented using some standard MSI constructs and in some cases some custom code in the Visual Studio external UI handler. Here is an outline of how things are implemented in the Visual Studio .NET 2003 family (which includes the .NET Framework SDK 1.1). I'm going to use the example of how we vertically integrate the .NET Framework SDK with Visual Studio .NET and refer to the MSI data for this, but there is similar data in the MSIs for other shared components as well. You can see all of this data by using the Orca tool in the MSI Platform SDK to open the vs_setup.msi or netfxsdk.msi and view the data:
This vertical integration strategy has caused us some headaches in the past. In Visual Studio .NET 2002 and 2003 and the .NET Framework SDK 1.0 and 1.1, it is not transparent to the user that setup changes the default install paths on its own and prevents users from changing the paths of the second and subsequent editions that are installed on the machine. There are odd scenarios where you can install one of the MSDN Quarterly documentation sets and then if you try to install Visual Studio or the .NET Framework SDK you cannot change the path and have no idea why not. In many of the internal scenarios that I have seen, we have had to resort to using MSI API calls to enumerate installed products and then checking against a known list to determine what other product prevents the Visual Studio path from being changed because there is not any good logging to track this type of issue down.
The worst case I saw of this was caught before we shipped Visual Studio .NET 2003 - someone had installed Visual Studio .NET 2002 and an MSDN Quarterly, and then when they installed a beta of Visual Studio .NET 2003 the path was redirected onto the VS 2002 install location and the user could not change it. In this particular case, the user didn't even notice it and ended up destroying their copy of VS 2002 (which should ordinarily install side-by-side with VS 2003) because all shared files were upgraded to the 2003 version and VS 2002 could not launch with a mismatch of some 2002 and some 2003 files. This issue was caused by the MSDN Quarterly picking up AppSearch entries that looked for some shared components within VS 2002's MSIs and some shared components within VS 2003's MSIs. We did a couple of last-minute tweaks to the VS 2003 vertical integration detection logic to avoid that issue when VS 2003 shipped.
Fortunately, in Visual Studio 2005 (codename Whidbey), this has been improved greatly - there is now visual indication in the setup UI that the path is not allowed to be changed and we generate a message on the fly indicating what product(s) we detected that are causing this behavior.
I know this post is long and detailed but I wanted to give some insight into how one of the features of Visual Studio and .NET Framework SDK setup works and also help illustrate some of the complicated engineering problems that have to be solved by setup. As Rob Mensching says in the header of his blog, setup isn't just an xcopy (in most cases....) :-)