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.
When I create an MSI-based installer, one of the things I typically include in the setup authoring is some logic to allow me to implement Windows Installer major upgrades if/when I need to release a new version of the MSI in the future. I typically include this authoring even if I don't currently plan to release a future version that I would need to use it for. Doing so gives me flexibility if/when I decide to update the MSI in the future.
There are some specific things you need to include in your MSI to enable major upgrades, and as I've learned about how to do this, I've found that the information is scattered around in several different places (MSDN, WiX documentation, blog posts, etc). As a result, I decided to create a couple of simple samples that I copy and paste from each time I create new MSI-based installers using WiX v3.0.
This blog post will use the samples that I created and posted at http://cid-27e6a35d1a492af7.skydrive.live.com/self.aspx/Blog%7C_Tools/WiX%20Samples/wix%7C_sample%7C_major%7C_upgrade.zip to demonstrate how to implement Windows Installer major upgrade functionality in an MSI created with WiX v3.0.
Step 1: Add upgrade information needed to cause new versions to upgrade older versions
In order to allow major upgrades, an MSI must include the following information:
Note - Windows Installer looks for other installed MSIs with the same UpgradeCode value during the FindRelatedProducts action. If you don't specifically schedule the FindRelatedProducts action in your setup authoring, WiX will automatically schedule it for you when it creates your MSI. I did not schedule FindRelatedProducts in the sample I created for this reason.
Step 2: Add logic to handle out-of-order installations (installing version 2 then trying to install version 1)
The information provided in step 1 will allow your MSI to uninstall older versions of your MSI during the install process for newer versions. In order to be complete, you should also include information in your MSI to handle scenarios where a user attempts to install a newer version of your MSI and then install an older version afterwards (an out-of-order installation). This step is not strictly necessary, but including this information in your MSI allows you to provide a more user-friendly experience in the case of an out-of-order installation scenario.
Detecting an out-of-order installation requires authoring another entry in the Upgrade table that defines a property that will be set if a newer version of the MSI is found on the user's system. From the example, this looks like the following:
<Upgrade Id="!(loc.Property_UpgradeCode)"> <UpgradeVersion Minimum="$(var.ProductVersion)" OnlyDetect="yes" Property="NEWERVERSIONDETECTED" /></Upgrade>
<Upgrade Id="!(loc.Property_UpgradeCode)"> <UpgradeVersion Minimum="$(var.ProductVersion)" OnlyDetect="yes" Property="NEWERVERSIONDETECTED" /></Upgrade>
Once you have defined the detection property, you need to decide how you want your MSI to behave in an out-of-order installation scenario and author an appropriate custom action. There are a couple of options:
A question that I have been asked in the past is why would an MSI want to immediately exit and return success instead of blocking and returning an error in an out-of-order installation scenario? The primary reason for this type of behavior is backwards compatibility for calling applications, particularly if the MSI is a redistributable component that can be shipped and installed as a part of other products. Here are a couple of examples of this type of scenario:
Step 3: Build version 1 and version 2 of your MSI
Creating version 1 of your MSI is as simple as running your standard build process - in WiX v3.0, this means you compile and link it with the WiX toolset. In order to create version 2 of your MSI, you must make the following changes to your setup authoring, then re-run your build process to create a new MSI:
In the example I created, I included scripts you can run on a system that has a build of WiX v3.0 installed in order to build 2 sets of MSIs:
Step 4: Test upgrade scenarios BEFORE YOU SHIP VERSION 1
This step is very important and in my past experience it has been too often ignored. In order to make sure that upgrade scenarios will behave the way you expect, you should test upgrades before you ship the first version of your MSI. There are some upgrade-related bugs that can be fixed purely by making fixes in version 2 or higher of your MSI, but there are some bugs that affect the uninstall of version 1 that must be fixed before you ship version 1. Once version 1 ships, you are essentially locked into the uninstall behavior that you ship with version 1, and that impacts major upgrade scenarios because Windows Installer performs an uninstall of version 1 behind the scenes during version 2 installation.
Here are some interesting scenarios to test:
When testing major upgrade scenarios, make sure to pay particular attention to custom actions in your MSI and assemblies that need to be installed to the GAC or the Win32 WinSxS store. Here are a few blog posts I've written in the past that contain examples of issues found during major upgrade testing:
Another more detailed example
While working on the sample for this blog post, I found the blog post at http://blogs.technet.com/alexshev/archive/2008/02/15/from-msi-to-wix-part-8-major-upgrade.aspx. This blog post contains more specific details about how Windows Installer behaves behind the scenes during a major upgrade, what information is required in an MSI for major upgrades, and how to map the information in the MSI rows/tables to WiX syntax. The example in that blog post was created with WiX v2.0 whereas the sample I posted uses WiX v3.0. The underlying concepts are the same, and the WiX syntax is only slightly different between v2.0 and v3.0. If you are interested in more detailed behind-the-scenes information about how major upgrades work, and/or if you are trying to implement a major upgrade that uses different settings than the ones presented in my example, I encourage you to check out this blog post as well.
<update date="3/12/2009"> Fixed broken link to the sample WiX source code for this post. </update>
I have tried to install the following versions of the .NET Framework on various different computers running Windows XP or Windows Server 2003:
In some cases, I have noticed that a folder gets left behind on the root of one of my drives. The folder has a randomly generated name, and it contains a copy of the setup files used to install the .NET Framework.
I do not see this behavior for the .NET Framework 1.0, the .NET Framework 1.1 or the .NET Framework 2.0.
Why is this folder left behind at this location after installing these versions of the .NET Framework? Can I safely delete this folder after I install the .NET Framework?
The installers for the .NET Framework 2.0 and earlier uses a legacy self-extracting EXE technology called IExpress. That technology creates a folder in the %temp% directory named something like IXP000.tmp (it will increment the number if a folder with this naming pattern already exists). Then it extracts the contents of the EXE to that folder and runs the setup EXE from within that folder. After the setup EXE completes, it will attempt to delete that folder.
The installers for the .NET Framework 3.0 and later use a different self-extracting EXE technology, which is why you have observed different behavior depending on what version of the .NET Framework you are trying to install. The self-extracting logic for these versions of the .NET Framework does the following:
One of the prerequisite packages for the .NET Framework 3.0 and higher - the XML Paper Specification (XPS) Shared Components Pack 1.0 - has a problem that causes the randomly named folder that it creates to fail to be deleted in step 5 above. Those files are temporary and only needed during the initial installation of this component, so it is safe to delete this randomly named folder if it ends up getting left behind on your system after .NET Framework installation completes.
I have heard of a few cases where attempting to delete the randomly named folder fails with a permission problem. I am not sure what causes that type of permission problem in the first place, but you will need to manually update the permissions on that folder in order to be able to delete it. Tools such as Cacls or SubInAcl could be useful to update these permissions if you run into this issue.
The XPS component is only installed by the .NET Framework setup package on Windows XP and Windows Server 2003, so the issue where this folder gets left behind at the end of .NET Framework setup will not affect newer operating systems such as Windows Vista, Windows Server 2008 or Windows 7.
<update date="12/21/2009"> Added more specific information about the root cause of this problem (the XPS setup package that is chained in during .NET Framework 3.0 and higher setup on Windows XP and Windows Server 2003). </update>
Starting with the Zune 3.0 firmware, you can install and play a set of games on your Zune device. Texas Hold Em, Hexic, Checkers, Sudoku and Space Battle are available in the Zune firmware and software that is available at the time that I am writing this blog post.
These in-box games are created with the XNA Framework, but they behave a bit differently than Zune games that you can create yourselves with XNA Game Studio 3.0. Specifically, many developers have asked on the forums why these games do not require a reboot of the Zune device when you exit them, whereas games created by other developers and deployed to the Zune device using XNA Game Studio 3.0 or via a .ccgame package do require a device reboot.
My colleague Michael Klucher has posted an item on his blog explaining more details about what is going on behind the scenes in these scenarios and why one set of games requires a device reboot and another set does not. If you are interested in learning more, I encourage you to read the blog post at http://klucher.com/blog/zune-games-and-rebooting-devices/.
Also, this scenario has been reported several times via the Connect bug reporting site. If this scenario is important to you, I encourage you to vote on this existing Connect bug (please vote on the existing bug instead of opening a new bug) so that the XNA will be aware of your feedback as we plan for future versions of XNA Game Studio and the XNA Framework.
I previously posted a couple of items about how to troubleshoot and work around issues in .NET Framework 3.0 and .NET Framework 3.5 setup that can be caused by failures in the ServiceModelReg.exe custom action:
Both of the above blog posts require digging through log files and event logs on your system in order to accurately narrow down the cause of .NET Framework 3.0 and 3.5 setup failures. In order to hopefully make resolving this type of issue quicker for most people, I wanted to post another option that is much more straightforward:
If you run into errors when installing the original version of the .NET Framework 3.0, the .NET Framework 3.0 SP1 or the original version of the .NET Framework 3.5, it will sometimes help to simply try to install the .NET Framework 3.5 SP1 instead.
The reason this can help is that the .NET Framework 3.5 SP1 installs the .NET Framework 3.0 SP2 behind the scenes as a prerequisite. There is a logic change in the .NET Framework 3.0 SP2 installer that will cause it to continue installing if the ServiceModelReg.exe custom action fails, whereas in previous versions of the .NET Framework 3.0, this failure would cause the entire installation process to fail and roll back.
If the ServiceModelReg.exe custom action fails during your .NET Framework 3.5 SP1 installation, you may not ever notice if none of the applications you use requires Windows Communication Foundation HTTP activation functionality. If it turns out that you do need this functionality later on, but the custom action failed during setup and things are not registered correctly, you can manually run the ServiceModelReg.exe tool because it is also installed as a part of the .NET Framework 3.0 and higher.
I want to mention one caveat here that I typically include in all of my .NET Framework troubleshooting blog posts - there are many possible causes for .NET Framework setup failures, and this blog post only describes one of them. The above workaround will likely not help solve all possible installation issues. If this workaround does not help in your scenario, then I suggest looking at the .NET Framework setup troubleshooting guide for links to other possible installation issues and workarounds, links to log file locations, links to readme files, etc.
While helping out a customer a few weeks ago, we discovered that the .NET Framework cleanup tool and the .NET Framework setup verification tool were not correctly opening, reading from or deleting 32-bit registry values on 64-bit versions of Windows (that is, registry values located under HKEY_LOCAL_MACHINE\Software\Wow6432Node for example).
As a result, the cleanup tool would leave behind some 32-bit registry values on 64-bit systems that could confuse the .NET Framework setup programs when they were run later on. Also, the .NET Framework verification tool would skip checking all 32-bit registry values that it was supposed to check on 64-bit OS's, and that could cause it to report successful installs even in cases where important registry keys/values were missing from the system or had incorrect data in them.
Over the Thanksgiving holiday, I updated both the cleanup tool and the verification tool with fixes to allow them to correctly handle 32-bit registry values on 64-bit OS's. These changes should not result in any behavior changes when running either of these tools on 32-bit OS's.
If you previously ran into any issues with either of these tools on a 64-bit OS, I encourage you to download the updated versions and try them again. Please let me know if you run into any problems with either of these tools.
For reference, here is additional information about these tools, including download links where you can get the latest versions of each of them:
Last week, Rob Mensching and Bob Arnson posted some information on their blogs about the upcoming declaration of a beta build of WiX v3.0 in preparation for locking down WiX v3.0 to get it ready to ship in Visual Studio 2010 (an older 3.0 build is currently available in the CTP).
This morning, the WiX 3.0.4805.0 build was published to the SourceForge release page (in addition to the normal weekly release page) and declared an official beta build. Here are links to more information about this build:
If you're using a build of WiX v3.0 to create your installers, you should upgrade to the 3.0.4805.0 build if possible in order to help validate the fixes that have been made over the past few months and help the WiX development team determine how close WiX v3.0 is to being done and ready to ship.
You can report issues that you find with the WiX toolset at the following locations:
Back when the .NET Framework 3.5 shipped, I posted a brief explanation about the size and contents of the .NET Framework 3.5 full installation package.
Recently, Scott Hanselman created a site called SmallestDotNet.com that includes script-based logic to detect the latest version of the .NET Framework that is installed on your system and list the minimal components that need to be installed in order to upgrade the system to the .NET Framework 3.5 SP1. This site also contains the code for a script block that you can copy and paste into your own web page if you want to use it for your deployment scenarios.
This type of detection logic can be useful for web-based installers for applications that require the .NET Framework 3.5, and in some scenarios it can be a useful alternative to the sample detection code that I posted on my blog (which is written in C++ and is intended for use by rich-client installers that users download and run on their systems).
Scott also describes the behind-the-scenes logic used by the SmallestDotNet.com site in a blog post at http://www.hanselman.com/blog/SmallestDotNetOnTheSizeOfTheNETFramework.aspx. In that blog post, he also describes more detail about the online and offline installers for various versions of the .NET Framework and options for minimizing download size in online install scenarios.