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.
A couple of colleagues of mine from my days on the Visual Studio and .NET Framework setup team have started blogging and I wanted to post links to their blogs here and encourage everyone to check them out. Quan has already posted some nice workarounds to tricky setup issues seen in the VS 2005 beta 2 and June 2005 CTP timeframes. Pete started working on the setup team at the same time I did back in the day, and we can swap stories about the old days of VS .NET 2002, .NET Framework 1.0, and all the growing pains we went through to get those products shipped :-)
You can check out their blogs at the following links:
Some products require that assemblies be installed to both the global assembly cache (GAC) and to the local file system. Windows Installer has native functionality that allows a setup author to do both. You can author an assembly as a global assembly (which will cause Windows Installer to install the file to the GAC) by adding it to the MsiAssembly and the MsiAssemblyName tables of the MSI and setting the File_Application column of the MsiAssembly table to Null. You can author an assembly as a private assembly (which will cause Windows Installer to install the file to the local file system) by adding it to the MsiAssembly table and setting the File_Application column to a file entry from the File table of the MSI. Windows Installer will take the file entry, look up the component that owns it and then use the directory entry associated with that component to install the private assembly to that same directory.
One of the first questions that comes up when a setup developer is trying to install an assembly to multiple locations is how to author the data in the MSI to install the same assembly component to both the GAC and the local file system. In most cases where a setup needs to install the same file to multiple locations, you can use the DuplicateFile table. Unfortunately, the DuplicateFile table does not support installing an assembly as both a global and a private assembly. In other words, you have the option to indicate that an assembly is a private assembly or a global assembly, but not both. In order to install the assembly to both the GAC and the local file system, you will have to create a second component and author one component as a global assembly and the other component as a private assembly.
We have to install assemblies to both locations as part of the .NET Framework and Visual Studio setups. In the case of the .NET Framework, the underlying architecture requires that the assemblies that are part it be installed to the GAC (for 3rd party applications) and to the local file system (for design-time scenarios in Visual Studio). However, we had to carry 2 copies of each assembly in the setup package in order to install to both places because Windows Installer doesn't support using the DuplicateFile table to do this. Carrying 2 copies of each assembly caused the overall size of the .NET Framework 1.0 and 1.1 redistributable setup package to grow even larger than it already was. After looking at a lot of different options, we decided to implement a custom action solution in .NET Framework 2.0 that would manage the installation of assemblies to both the GAC and the local file system. This allowed us to only carry a single copy of each file in the setup package and reduce the overall size of the .NET Framework setup by about 5 megabytes. Of course, if you compare the size of dotnetfx.exe between versions 1.1 and 2.0 you won't see much of a difference. What ended up happening was that the size of the features added in .NET 2.0 roughly cancelled out the size of the assemblies that we were carrying duplicate copies of in .NET 1.1.
The .NET Framework 1.1 ships as an OS component on the 32-bit Windows Server 2003 family of operating systems. This .NET Framework component is a hidden, always-installed component with the exception of ASP.NET (which can be found as a selectable item underneath the Application Server item in the Add/Remove Windows Components control panel applet).
I have seen cases where the .NET Framework 1.1 stops working correctly on Windows Server 2003 (often due to bugs in daily builds of the .NET Framework 2.0). In those cases, it is useful to perform a repair to get the .NET Framework 1.1 back to a known good state. However, it can be difficult to figure out how to repair .NET 1.1 in these scenarios because the component is hidden and because there is some specific logic in the setup DLL that installs this component that prevents uninstall and reinstall after OS setup has completed.
In general, you can repair the .NET Framework 1.1 that ships with Windows Server 2003 by re-running OS setup and choosing to repair/reinstall, which will trigger the .NET Framework 1.1 component setup to rerun.
In addition, the following steps can be performed in order to repair the .NET Framework 1.1 on Windows Server 2003 while also avoiding the need to run a full OS reinstall:
<update date="11/1/2005"> There is a Knowledge Base article that also describes how to troubleshoot .NET Framework 1.1 installation issues on Windows Server 2003 that can be useful in this type of scenarios. You can find it at this location. </update>
<update date="9/29/2008"> Added a note about using source files with integrated service packs if the OS was originally installed with a service pack integrated. </update>
I have been working on the .NET Framework setup since before v1.0 shipped, and in that time I've seen all sorts of bugs and setup failures. There is one particularly tricky set of bugs that all show the same symptom but that we haven't been able to track down a common root cause for. The error that is seen during setup is a failure to register System.EnterpriseServices.dll or a problem running RegSvcs.exe /bootstrapi, which then causes setup to stop and rollback.
Almost none of the cases I have seen where this error appears were actually caused by the file System.EnterpriseServices.dll itself. It is a bit misleading because the registration of this file is done by a custom action during setup, and that custom action is the first time that the version of the CLR we are trying to install is used to run managed code on the computer. So that means that if anything is wrong on the machine to cause that version of the CLR to not work properly, the error the user sees is that this DLL failed to register.
When we encounter an error like this, we typically try the following cleanup and troubleshooting steps in the order listed below.
In many cases, running the cleanup tool is sufficient, but every once in a while we run into a computer in a state that we can't diagnose and we have to try some more advanced debugging techniques like those listed in steps 2 and 3.
We use the following steps to configure the MsiBreak environment variable to cause .NET Framework setup to pause at the beginning of the custom action that registers System.EnterpriseServices.dll, attach a debugger and gather crash dump information:
Variations of the above steps can also be used to gather debugging information for any custom action that fails during an MSI-based setup as long as you are able to consistently reproduce the crash during setup. You just need to substitute the appropriate custom action name in step 5 (by looking at the verbose MSI log file or looking at the MSI in Orca to get the exact name). You also need to substitute the custom action name and command line parameters in steps 9 and 10 above. In the case of this example, the custom actions are executable files that are installed as a part of .NET Framework setup. If the custom action is a file streamed into the binary table of the MSI, I believe you will need to extract the file from the MSI and run it using rundll32.exe or something like that (but I haven't yet tried to do that to verify that it works like I think it will).
<update date="9/25/2006"> Added a note about running WinDBG with elevated privileges on Windows Vista </update>
I have heard from a few people (including this customer comment on a previous blog post and a fellow Microsoft employee) who have tried to install VS 2005 beta 2 and received 1935 (or 2908) assembly install errors with HRESULT value 0x8002802F. If you take a look at my 1935 troubleshooting guide, you will see that this error means "function not defined in specified DLL." When this error occurs during .NET Framework or VS setup, it generally means that the version of mscoree.dll located in %windir%\system32 on the computer does not match the version needed by Windows Installer to call specific Fusion APIs to install assemblies to the GAC.
In the case of the Microsoft employee who contacted me, VS setup detected that the .NET Framework 2.0 was already installed and skipped that prerequisite step. However, the machine actually only had .NET Framework 1.1 installed, and the version of %windir%\system32\mscoree.dll was 1.1.4322.573. When VS setup tried to install assemblies to the GAC, it failed because Windows Installer tried to call into a 2.0-specific API from mscoree.dll (needed because there are new processor architecture attributes on VS 2005 assemblies that only 2.0 knows about). Since the version of mscoree.dll on the system was 1.1, these API calls failed.
I found that this computer had the following orphaned registry key/value that VS setup found and used to determine that .NET Framework 2.0 beta 2 was already installed:
On this employee's machine, once I deleted this key/value and re-ran VS 2005 beta 2 setup, it detected that it needed to install the .NET Framework 2.0 beta 2. Once that completed, VS setup worked perfectly.
As a side note if you're really interested, you could use some of the setup reverse engineering tricks that I describe here to determine the exact location of this registry key. In this case, the key/value are listed in the [gencomp18] section of the file named baseline.dat in the setup subdirectory of the VS 2005 beta 2 DVD.
I found this blog post that I wanted to link to here as well. Yosi provides a good set of troubleshooting steps and a workaround if you are seeing performance problems creating team projects using Visual Studio 2005 Team System. In a nutshell - you can configure Internet Explorer to not use your proxy server and significantly improve the startup time when creating new team projects in multi-server scenarios.
If anyone has tried to install Visual Studio 2005 beta 2 on Windows XP Professional x64 Edition, I am sure you have noticed that installation does not work correctly because VS setup says that you need to install Windows XP Service Pack 2 even though there is not an SP2 available for Windows XP Professional x64 Edition. This is a bug in setup for Visual Studio 2005 beta 2 that has been fixed in later builds.
In the meantime, you can workaround this issue by doing one of the following:
-or-
<updated on June 6, 2005 - reworded one of the caveats and moved it to be caveat #1 based on the comment from HeathS about the requirement that Windows Installer 3.x be present in order to install .NET Framework 2.0 hotfixes or service packs>
Some of you may have noticed that .NET Framework 2.0 beta 2 requires a minimum version of Windows Installer 3.0 and if it is not installed on the computer, you will have to download it and install it as a separate step. This is a change from .NET Framework 2.0 beta 1, which required a minimum version of Windows Installer 2.0 and carried the installation packages for Windows Installer 2.0 as part of the dotnetfx.exe package.
The increased minimum requirement from Windows Installer 2.0 to Windows Installer 3.0 (and possibly to 3.1 by the time .NET Framework 2.0 ships) is due to a lot of servicing/patching fixes available in Windows Installer 3.x. Since there aren't any strict setup-time requirements for Windows Installer 3.0 in the .NET Framework setup, you can use some unsupported reverse engineering tricks to make .NET Framework 2.0 beta 2 setup work if you only have Windows Installer 2.0 installed.
Before I list the steps I want to list a couple of important caveats:
With that out of the way, here are the steps you can use to get .NET Framework 2.0 beta 2 to install on a machine with only Windows Installer 2.0 present:
Note that if you want to use these steps for one of the 64-bit versions of .NET Framework 2.0, you should substitute "netfx64.exe" for every instance of "dotnetfx.exe" above.
I found an article in PCWorld this week that talks about a new Windows Media Center computer being produced by Shuttle with Always Ready technology. Always Ready is sort of a sub-sleep state that allows Media Center to go into a deep hibernation, which is useful to conserve energy and reduce noise. But the machine remains available to do things like record TV programs, and it is able to start back up from the sub-sleep state very quickly. For example, the Shuttle machine in the article could start up in less than 5 seconds.
There is also a slide deck from WinHec 2004 that introduces and explains Always Ready from a theoretical standpoint that I found pretty interesting.
<updated on June 3, 2005 - changed the product name from "SQL Server Tools Express" to "Microsoft SQL Server 2005 Tools Express Edition CTP" based on the full official name as it appears in Add/Remove Programs>
There is a known setup interaction issue with beta versions of SQL Server 2005 (codename Yukon). There is a conflict between the SQL Tools that are installed with SQL Express 2005 Beta and the SQL Tools that are installed with the full SQL Server 2005 Beta. If SQL Server 2005 Beta with SQL Tools is installed then SQL Express will fail, and vice versa.
You can workaround this issue by doing one of the following:
Scenario 1 - Install SQL Express first
Scenario 2 - Install SQL Server 2005 Beta first
This workaround should work for the version of SQL Express that is included with VS 2005 beta 1 and VS 2005 beta 2. This scenario is a known issue that the SQL team is planning to address before SQL Server 2005 releases.