In Part 1 we looked at the steps required to create a Windows Installer using Wix that dynamically packages the binaries from a target .NET application ready for deployment. In this part we'll look at adding some condition checks into the installer that prevents a user from installing the software unless some conditions are met.
In our solution we will create condition checks for the following:
- Install only on Windows 7
- Install only if the Microsoft .NET Framework 4 Client Profile is installed
- Install only on Dell hardware
Wix provides a variety of ways to add condition checks using registry or file system searches for example. When a condition element is added as a child node of the
Project element it will only allow installation when the condition is met. If not the installation will be terminated with the given error message.
Windows 7 Condition
To add a condition that prevents users from installing the application on versions of Windows other than Windows 7 we can leverage some existing properties populated by Windows Installer. These are the
WindowsBuild properties. If we look at the documentation for Operating System Property Values we find that the required values for detecting Windows 7 are VersionNT 601 and WindowsBuild greater than 7100.
To implement the condition we add the following element into the
Main.wxs file within the
<Condition Message='[ProductName] can only be installed on Windows 7' > VersionNT = 601 AND WindowsBuild > 7100 </Condition>
The result is that the installer will now only install the application on devices running Windows 7, otherwise an error is thrown and the installation is terminated.
Microsoft .NET Framework 4 Client Profile Condition
WixNetFxExtension.dll extension used in Part 1 provides a set of useful utilities related to the .NET framework and this includes properties that can be used for detecting the version of the .NET framework that is currently installed.
Unfortunately version 3.0 of the framework doesn't include a property for detecting .NET 4.0 and this will only be available in Wix 3.5. Luckily detecting if a particular version of the framework is installed isn't too difficult, and we can use a simple registry search as follows:
<Property Id="NETFRAMEWORK40CLIENT"> <RegistrySearch Id="NetFramework40Client" Root="HKLM" Key="SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Client" Name="Install" Type="raw" /> </Property>
This populates a property named
NETFRAMEWORK40CLIENT with a value of 1 if the registry key is found. Using this we can then implement the condition check. We skip the condition check on uninstall in case the framework is subsequently removed.
<Condition Message="[ProductName] requires the Microsoft .NET Framework 4 Client Profile"> Installed Or NETFRAMEWORK40CLIENT </Condition>
Dell Hardware Condition
To implement a hardware check we need to perform a WMI lookup to determine the hardware manufacturer. To get the WMI value into Windows Installer so that we can implement a condition we need to use a custom action.
There are a variety of ways to implement a custom action. For simplicity in this case we will use an embedded VBScript called
WMIQuery.vbs. The script will perform the WMI lookup and poke this into the installer as a property named
To begin we add a reference to the
WMIQuery.vbs file using a
Binary element. We then define a custom action that will invoke a function within the script and schedule this to run after
AppSearch in the
InstallUISequence sequences. This makes the property available prior to running the condition checks during install.
The new code looks something like this:
<Condition Message='This application cannot be installed on this hardware.'> <![CDATA[ SKIPCHECK OR Installed OR WMI_Manufacturer >< "dell" ]]> </Condition> <CustomAction Id="WMIQuery" Return="check" BinaryKey="WMIQuery" VBScriptCall="Main" /> <Binary Id="WMIQuery" SourceFile="Binary\WMIQuery.vbs" /> <InstallExecuteSequence> <Custom Action="WMIQuery" After="AppSearch" /> </InstallExecuteSequence> <InstallUISequence> <Custom Action="WMIQuery" After="AppSearch" /> </InstallUISequence>
Note the use of the contains string operator
>< for the condition check. The operator characters must be escaped within
CDATA blocks to prevent validation issues with the XML. We have also added an override property called
SKIPCHECK that will allow us to override the hardware condition when run from the command line for testing. To do this we execute the MSI as follows:
msiexec /i setup.msi SKIPCHECK=1
So far in this series we have looked at creating a Windows Installer using Wix which dynamically packages a .NET application and applies NGen against the assemblies during installation. We have now also added some conditions to prevent the application being installed in specific scenarios using a range of techniques. In Part 3 we will look at localizing the installer and providing auto-language detection using the user's region settings. Part 3.