I was looking at the setup package for the x64 version of the .NET Framework beta 2 recently. I needed to try to install it on a Windows Vista machine in order to work on an issue related to Media Center, and I got an interesting error telling me "Microsoft .NET Framework 2.0 (x64) is not supported on Windows 95, Windows NT, Windows 2000 without Service Pack 3 or greater, and Windows Server 2003 without Service Pack 1 or greater." Granted, it isn't really a valid scenario to try to install the MSI-based .NET Framework 2.0 package on Vista because the .NET Framework 2.0 is already part of the OS, but since I got this error message that blocked me but listed a completely wrong set of OS's, I had to dig a little deeper at least to satisfy my own curiosity.
While I was looking at the MSI, I came across this condition in the LaunchCondition table:
(Version9X >= 410) OR ((VersionNT = 500) AND (ServicePackLevel >= 3)) OR (VersionNT = 501) OR ((VersionNT = 502) AND (ServicePackLevel >= 1))
I stared at this set of conditions for a while because something just felt wrong about it. Then it came to me - this launch condition is listing the OS's that the MSI will allow the .NET Framework 2.0 x64 version to install on. Notice that the supported versions stop with VersionNT = 502. Since the VersionNT value 502 is equivalent to Windows Server 2003, it would block installation on any OS with a version number higher than Windows Server 2003. That is fine for Vista because .NET 2.0 will already be a part of the OS, but that is not fine for future versions of Windows after Vista.
To make a long story short, I reported a bug on this issue and they're considering a fix for it for the final version of .NET Framework 2.0 x64 and ia64 editions. However, I thought it illustrated a couple of more important points to keep in mind when designing an MSI-based setup:
- Be careful with using LaunchConditions. The logic can be confusing and convoluted and getting them wrong will block your setup from being allowed to run, which is fairly painful to try to patch or recover from. We put a launch condition in for the .NET Framework 1.1 to block installation on 64-bit platforms but then after 1.1 shipped Microsoft started releasing 64-bit OS's, and the application compatibility team had to add a shim to the OS to override this launch condition that was no longer valid.
- Try to keep the future in mind when designing your setup whenever possible. In my experience, this is really hard to do but very important. For example, do not limit your setup authoring to only account for operating systems that are available when your product ships. Think about making your version detection generic unless there is some specific reason you would not want your users to install your product on some future OS. Also, think about whether you will be releasing future versions of the product and whether or not you want to have both versions co-exist on the same machine - and if so, learn and know the MSI component rules and apply them to the design of all versions of your product. We did not get things exactly right for the .NET Framework 1.0 and that is why you will see files named sbs*.dll installed to %windir%\Microsoft.NET\Framework with all versions 1.1 and higher - these files bail us out in uninstall scenarios by adding extra component ref-counts to some resources that would otherwise be uninstalled incorrectly.