An in-depth look at the .NET Framework 2.0 setup INI file

I have been looking at some of the previous topics that I intended to write follow-up articles for to try to provide more detailed information. One of them is this article I wrote a couple of months ago where I introduced the external UI handler that we use to install the .NET Framework 2.0 and some other packages that will ship as part of Visual Studio 2005. I wanted to pick this back up now that VS 2005 and .NET 2.0 are getting closer to shipping because I think some of this information will be interesting to people interesting in including .NET Framework 2.0 in their setup package and/or customizing the behavior of .NET Framework 2.0 setup.

For this post, I want to take a more detailed look at the INI file that is used by the .NET Framework 2.0 setup wrapper. To begin with, we need to download a copy of the .NET Framework 2.0. I am going to use the release candidate, but you can download the latest beta version located here and follow along with me. I'm not sure the best way to approach this, so I'm going to try the strategy of listing the contents of the INI file and adding my own comments to each line describing more about what parts of setup they control. Not all options supported by the setup wrapper are used in the .NET Framework setup INI file, so I will explore other types of supported settings in a future blog post...

[Setup] // This is the section of the INI that contains "global" data that is used to configure major settings for the setup wrapper
ProductName=Microsoft .NET Framework 2.0 // The name displayed in all of the setup UI title bars
ProductMsi=netfx.msi // The name of the MSI that is included with the setup UI files that will be installed
ProductRegKey=SOFTWARE\Microsoft\NET Framework Setup\NDP\v2.0.50727 // Registry key name under HKEY_LOCAL_MACHINE that contains a value that setup should check for and block installation if it exists because the product is already installed using some other setup technology. This is designed to allow .NET Framework 2.0 MSI-based setup to block on Windows Vista because .NET 2.0 is installed as part of the OS
ProductRegValue=OCM // Name of a DWORD registry value located in the location referred to by ProductRegKey; setup will check to see if this value exists and is equal to 1 and if so, will block installation and tell the user that the product is already installed as part of the OS
ProductSupportURL=https://go.microsoft.com/fwlink/?LinkId=45396 // This URL is displayed in setup UI to provide readme information, such as when setup fails
DefaultDirInstallToken=URTInstallPath.3643236F_FC70_11D3_A536_0090278A1BB8 // The directory token in the MSI that represents the default install path; this is used in setup UI for products that allow changing the install path
SupportWin9X=1 // Whether or not this setup package should allow installation on Windows 98, 98 SE, or ME
MinNTVersion=5.0 // The minimum NT version that setup should allow installation on; version 5.0 = Windows 2000 (and 4.0 = NT4, 5.1 = Windows XP, 5.2 = Windows Server 2003)
CheckAdminRights=1 // Whether or not this setup package should check for administrative privileges and block setup from running unless the calling process has administrative privileges
ShowFeatureOptions=0 // Whether or not setup UI should show the page that allows the user to select features to install
ShowDestinationFolder=0 // Whether or not setup UI should show the page that allows the user to change the install path for the product; the default value if this page is shown is the directory represented by the DefaultDirInstallToken value above
LogFilePrefix=dd_netfx20 // The name to use as the prefix for log files generated by this product; there will be 2 logs created - dd_netfx20ui*.txt and dd_netfx20msi*.txt. The * is a randomly generated suffix, and these logs are always created in the %temp% directory; the UI log is a record of activities performed by the setup wrapper itself, and the MSI log is an MSI log created by Windows Installer while the product is installing
VerboseLog=1 // Whether or not to create a verbose MSI log during installation
RebootMode=1 // Whether or not the user will be offered a checkbox that lets them postpone a reboot at the end of installation
BlockOn64Platform=1 // Whether or not the setup should block installing on 64-bit versions of Windows
BitmapFile=netfx.bmp // The name of a file contained in the setup package that has a small bitmap that is displayed in the top right corner of all setup UI wizard pages; in the case of the .NET Framework, it is just a blank bitmap so there is no logo displayed in the wizard UI
CustomTextPrefix=CustomText // The prefix of a DLL that contains custom strings that will be displayed on the first and/or last page of setup UI; setup expects the DLL name to begin with this prefix then have .LCID.dll as the ending (where LCID is the 4-digit language code for the language of the resources in the DLL); for example, if the .NET Framework setup carried a file named CustomText.1033.dll, setup UI will try to load resources from that file to customize the UI on the first and last page; if the DLL does not exist, setup UI will display the page with the default text and not show any custom UI for this product
UninstallWarning=1 // Whether or not to show an advisory dialog at the beginning of uninstall to advise that uninstalling this product may break other dependent products
ControlMSIService=1 // Whether or not the setup wrapper should stop the Windows Installer service before and after installation
UILanguage=0 // The default UI language to use for this setup package; setting it to 0 means it is language neutral and will attempt to load the UI in the language of the OS; setting it to a specific LCID will cause it to load the UI in the specific language; the UI DLLs are carried with the setup package and are named install.res.LCID.dll; in addition, the EULA files are carried with the package and are named eula.LCID.txt

[DetectDarwin] // This section tells the setup wrapper whether or not to enforce a specific version of Windows Installer as a prerequisite
X86=3.0 // The Windows Installer version to search for on x86 machines
I64=3.0 // The Windows Installer version to search for on Intel 64-bit machines
A64=3.0 // The Windows Installer version to search for on AMD x64 machines
Win9x=2.0 // The Windows Installer version to search for on Windows 98/ME machines
NT4=2.0 // The Windows Installer version to search for on NT4 machines
Install=0 // Whether or not the setup wrapper should check for Windows Installer or install it if it is not present; we used to set this to 1 and install Windows Installer if it was needed; unfortunately, this feature is orphaned now and the code only knows how to bootstrap and install Windows Installer 2.0; it will not correctly install Windows Installer 3.0 or higher because the setup packaging is different and the command line parameters the setup wrapper passes in to install Windows Installer are hard-coded
Link=https://go.microsoft.com/fwlink/?LinkId=45724 // Link to provide to users on Windows 2000 and higher machines if the required version of Windows Installer is not present and the Install value = 0; this link should point to the install location for the required version of Windows Installer
Link9x=https://go.microsoft.com/fwlink/?LinkId=45725 // Link to provide to users on Win9x-based machines if the required version of Windows Installer is not present and the Install value = 0; this link should point to the install location for the required version of Windows Installer
LinkNT4=https://go.microsoft.com/fwlink/?LinkId=45726 // Link to provide to users on NT4 machines if the required version of Windows Installer is not present and the Install value = 0; this link should point to the install location for the required version of Windows Installer

[DetectIE] // This section tells the setup wrapper whether or not to enforce a specific version of Internet Explorer as a prerequisite
X86=5.0.2919.6307 // The Internet Explorer version to search for on x86 machines
A64=5.0.2919.6307 // The Internet Explorer version to search for on AMD x64 machines
I64=5.0.2919.6307 // The Internet Explorer version to search for on Intel 64-bit machines
Link=https://www.microsoft.com/windows/ie/default.asp // Link to provide to users if the required version of Internet Explorer is not present; this link should point to the install location for the required version of Internet Explorer
VersionDisplay=5.01 // Friendly version number to display to the user in setup UI when this block is hit

[DetectNetFx] // This section tells the setup wrapper whether or not to enforce a specific version of the .NET Framework as a prerequisite; setup looks for the registry value HKLM\Software\Microsoft\NET Framework Setup\NDP\v<version>\<optional lang value>\Install = 1
X86=2.0.50727 // The .NET Framework version to search for on x86 machines; replaces <version> in the registry key name listed above
A64=2.0.50727 // The .NET Framework version to search for on AMD x64 machines; replaces <version> in the registry key name listed above
I64=2.0.50727 // The .NET Framework version to search for on Intel 64-bit machines; replaces <version> in the registry key name listed above
Link=https://go.microsoft.com/fwlink/?linkid=27895 // Link to provide to users if the required version of the .NET Framework is not present; this link should point to the install location for the required version of the .NET Framework
Lang=1033 // The LCID for the language of the .NET Framework that must be installed; replaces the <optional lang value> in the registry key name listed above if LangDetectionNeutral = 0; if this value = 1033, this detection section is skipped entirely (this logic is in place to allow for easier creation of non-English INI files in the build process for VS and the .NET Framework)
LangDetectionNeutral=1 // Whether or not to append the Lang value as part of the registry key used to determine whether or not the version of the .NET Framework is already installed; if this equals 0, setup will append the Lang value, and if it is equal to 1 it will not

[BlockProductCode] // List of product codes that the setup wrapper should check for the presence of; if any are found, setup will block and tell the user to uninstall the products associated by the product codes
{018F3F06-CDA6-492C-9B45-3687E29B7BC6}= // Each GUID is an MSI product code; it has an equal sign because the parser for the INI file expects strings in each section to be in the form <value> = <data>
<additional GUIDs removed from the real install.ini for length reasons>

[VSSetupWatson] // This section is used to collect Watson data when setup fails so that we can track the type of failures and offer remediation steps as we identify root causes and post workarounds via the Watson server; these values are all used to categorize the issues on the Watson server
VSSWSuccessEnabled=1
VSSWSuccessHeadless=1
VSSWFailedEnabled=1
VSSWFailedHeadless=1
VSSWProdName=Microsoft .NET Framework 2.0
VSSWProdVer=8.0.50727.42_RTM_x86ret
VSSWSectionEnabled=1
VSSWProdSAID=183
VSSWInternalRelease=1