Skip to content

Instantly share code, notes, and snippets.

@N7K4
Last active June 9, 2022 09:42
Show Gist options
  • Save N7K4/8b146328db03484a61543c4f612c5dd3 to your computer and use it in GitHub Desktop.
Save N7K4/8b146328db03484a61543c4f612c5dd3 to your computer and use it in GitHub Desktop.
Add a prerequisites page to Windows Installer created with wix toolset v3 installer based on WixUI_FeatureTree

Intro

This GIST shows how to add an additional page to the Windows Installer (MSI-part) using the wix toolset version 3. I choose the WixUI_FeatureTree as customization.

This GIST is part of the WixToolset-Tutorials.

I was inspired by stackoverflow.com Add pages to installer -Wix Toolset.

Steps

  1. Download PrerequisitesDlg.wxs from this GIST on GitHub and copy it to your project folder
  2. Download WixUI_FeatureTree.wxs from GitHub. The file is inside WixToolset v3 on GitHub src/ext/UIExtension/wixlib/WixUI_FeatureTree.wxs. Copy it to your project folder
  3. Rename the file WixUI_FeatureTree.wxs to WixUI_KargWareFeatureTree.wxs
  4. Add the WiX Extension WixUIExtension as reference to your wixproj project file (when it is not there). The extension is located at C:\Program Files (x86)\WiX Toolset v3.11\bin\\WixUIExtension.dll
  5. Add PrerequisitesDlg.wxs and WixUI_KargWareFeatureTree.wxs to your wixproj project file
  6. Add translation / localisation strings and images to your *.wxl files or create the translation files
  7. Open the WixUI_KargWareFeatureTree.wxs and change the Id of the UI-element from <UI Id="WixUI_FeatureTree" to <UI Id="WixUI_KargWareFeatureTree">
  8. Wrap all Conditions inside WixUI_KargWareFeatureTree.wxs for better reading with <![CDATA[ xyz ]]>
  9. Add the <Publish Dialog="PrerequisitesDlg" ... element inside the UI-Element of WixUI_KargWareFeatureTree.wxs
  10. Add <UIRef Id="WixUI_KargWareFeatureTree"/> in the Product.wxs inside the <Product></Product> element
  11. Set prerequisites as Property with 'PreRegXXXRequiered' as (localization-able) text and the Condition 'PREREGXXXCONDITION' (XXX is a value from 1 to 5) in the Product.wxs inside the <Product></Product> element. Condition 1 or 1=1 can be used to that a condition to true
  12. Too omit the PrerequisitesDlg remove all PreRegXXXFoundText properties
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<!--
### 0. THIS FILE CAN BE USED AS IT IS. YOU DON'T NEED TO CHANGE IT
### **************************************************************
Source GitHub Gist https://gist.github.com/N7K4/8b146328db03484a61543c4f612c5dd3#file-prerequisitesdlg-wxs
-->
<!--
### 1. PLEASE ADD THESE TRANSLATION TO ALL OF YOUR WSL FILES
### ********************************************************
<WixLocalization Culture="en-US" Codepage="1252" xmlns="http://schemas.microsoft.com/wix/2006/localization">
<String Id="PrerequisitesDlg_Title">[ProductName] Setup</String>
<String Id="PrerequisitesDlgBitmap">WixUI_Bmp_Banner</String>
<String Id="PrerequisitesDlgTitle">Prerequisites of [ProductName]</String>
<String Id="PrerequisitesDlgDescription">List and state of prerequisites.</String>
</WixLocalization>
-->
<!--
### 2. ADD 'PreRegXXXRequiered' AND 'PREREGXXXCONDITION' FROM 1 TO 5 TO YOUR PRODUCT.WXS
### ************************************************************************************
This Dialog supports up to 5 prerequisites.
The prerequisites can be set as Property with 'PreRegXXXRequiered' as localization text and the Condition 'PREREGXXXCONDITION' (XXX is a value from 1 to 5).
When the `PreRegXXXRequiered` is not set, the value will be set to 'EmptyPrerequisites' and the field will disappear on the dialog
-->
<!--
### 3. SET LAUNCHCONDITIONS TO YOUR PRODUCT.WXS
### *******************************************
The prerequisites can block the whole installer byusing launch conditions.
Just use the 'PREREGXXXCONDITION' directly or set the property by a WiX-Variable.
-->
<WixVariable Id="EmptyPrerequisites" Value="----" Overridable="no"/>
<Property Id="PREREG1CONDITION" Secure="yes" />
<Property Id="PREREG2CONDITION" Secure="yes" />
<Property Id="PREREG3CONDITION" Secure="yes" />
<Property Id="PREREG4CONDITION" Secure="yes" />
<Property Id="PREREG5CONDITION" Secure="yes" />
<Property Id="PreReg1FoundText" Value="!(wix.EmptyPrerequisites)" />
<Property Id="PreReg2FoundText" Value="!(wix.EmptyPrerequisites)" />
<Property Id="PreReg3FoundText" Value="!(wix.EmptyPrerequisites)" />
<Property Id="PreReg4FoundText" Value="!(wix.EmptyPrerequisites)" />
<Property Id="PreReg5FoundText" Value="!(wix.EmptyPrerequisites)" />
<SetProperty Id="PreReg1Checked" Value="1" Sequence="ui" Before="CostFinalize"><![CDATA[PREREG1CONDITION]]></SetProperty>
<SetProperty Id="PreReg2Checked" Value="1" Sequence="ui" Before="CostFinalize"><![CDATA[PREREG2CONDITION]]></SetProperty>
<SetProperty Id="PreReg3Checked" Value="1" Sequence="ui" Before="CostFinalize"><![CDATA[PREREG3CONDITION]]></SetProperty>
<SetProperty Id="PreReg4Checked" Value="1" Sequence="ui" Before="CostFinalize"><![CDATA[PREREG4CONDITION]]></SetProperty>
<SetProperty Id="PreReg5Checked" Value="1" Sequence="ui" Before="CostFinalize"><![CDATA[PREREG5CONDITION]]></SetProperty>
<SetProperty Id="PreReg1Requiered" Value="1" Sequence="ui" Before="CostFinalize"><![CDATA[PreReg1FoundText <> "!(wix.EmptyPrerequisites)"]]></SetProperty>
<SetProperty Id="PreReg2Requiered" Value="1" Sequence="ui" Before="CostFinalize"><![CDATA[PreReg2FoundText <> "!(wix.EmptyPrerequisites)"]]></SetProperty>
<SetProperty Id="PreReg3Requiered" Value="1" Sequence="ui" Before="CostFinalize"><![CDATA[PreReg3FoundText <> "!(wix.EmptyPrerequisites)"]]></SetProperty>
<SetProperty Id="PreReg4Requiered" Value="1" Sequence="ui" Before="CostFinalize"><![CDATA[PreReg4FoundText <> "!(wix.EmptyPrerequisites)"]]></SetProperty>
<SetProperty Id="PreReg5Requiered" Value="1" Sequence="ui" Before="CostFinalize"><![CDATA[PreReg5FoundText <> "!(wix.EmptyPrerequisites)"]]></SetProperty>
<SetProperty Id="pr1OK" Value="1" Sequence="ui" Before="SetAllLauchConditions"><![CDATA[((NOT PreReg1Requiered) OR (PreReg1Requiered AND PreReg1Checked))]]></SetProperty>
<SetProperty Id="pr2OK" Value="1" Sequence="ui" Before="SetAllLauchConditions"><![CDATA[((NOT PreReg2Requiered) OR (PreReg2Requiered AND PreReg2Checked))]]></SetProperty>
<SetProperty Id="pr3OK" Value="1" Sequence="ui" Before="SetAllLauchConditions"><![CDATA[((NOT PreReg3Requiered) OR (PreReg3Requiered AND PreReg3Checked))]]></SetProperty>
<SetProperty Id="pr4OK" Value="1" Sequence="ui" Before="SetAllLauchConditions"><![CDATA[((NOT PreReg4Requiered) OR (PreReg4Requiered AND PreReg4Checked))]]></SetProperty>
<SetProperty Id="pr5OK" Value="1" Sequence="ui" Before="SetAllLauchConditions"><![CDATA[((NOT PreReg5Requiered) OR (PreReg5Requiered AND PreReg5Checked))]]></SetProperty>
<SetProperty Id="AllLauchConditions" Value="1" Sequence="ui" After="CostFinalize">
<![CDATA[(pr1OK AND pr2OK AND pr3OK AND pr4OK AND pr5OK)]]>
</SetProperty>
<UI>
<Dialog Id="PrerequisitesDlg" Width="370" Height="270" Title="!(loc.PrerequisitesDlg_Title)">
<Control Id="ProductVersion" Type="Text" X="10" Y="243" Width="56" Height="17" Text="[ProductVersion]" />
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.WixUINext)" >
<Condition Action="disable">NOT AllLauchConditions</Condition>
</Control>
<Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="!(loc.WixUIBack)" />
<Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="!(loc.WixUICancel)">
<Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
</Control>
<Control Id="BannerHeader" Type="Text" X="15" Y="6" Width="280" Height="15" Transparent="yes" NoPrefix="yes" Text="!(loc.PrerequisitesDlgTitle)" />
<Control Id="BannerSubHeader" Type="Text" X="15" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes" Text="!(loc.PrerequisitesDlgDescription)" />
<Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="!(loc.PrerequisitesDlgBitmap)" />
<Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
<Control Id="PreReg1" Type="CheckBox" X="20" Y="70" Width="330" Height="18" CheckBoxValue="1" Hidden="yes" Property="PreReg1Checked" Text="[PreReg1FoundText]" Disabled="yes">
<Condition Action="show">PreReg1Requiered</Condition>
</Control>
<Control Id="PreReg2" Type="CheckBox" X="20" Y="90" Width="330" Height="18" CheckBoxValue="1" Hidden="yes" Property="PreReg2Checked" Text="[PreReg2FoundText]" Disabled="yes">
<Condition Action="show">PreReg2Requiered</Condition>
</Control>
<Control Id="PreReg3" Type="CheckBox" X="20" Y="110" Width="330" Height="18" CheckBoxValue="1" Hidden="yes" Property="PreReg3Checked" Text="[PreReg3FoundText]" Disabled="yes">
<Condition Action="show">PreReg3Requiered</Condition>
</Control>
<Control Id="PreReg4" Type="CheckBox" X="20" Y="130" Width="330" Height="18" CheckBoxValue="1" Hidden="yes" Property="PreReg4Checked" Text="[PreReg4FoundText]" Disabled="yes">
<Condition Action="show">PreReg4Requiered</Condition>
</Control>
<Control Id="PreReg5" Type="CheckBox" X="20" Y="150" Width="330" Height="18" CheckBoxValue="1" Hidden="yes" Property="PreReg5Checked" Text="[PreReg5FoundText]" Disabled="yes">
<Condition Action="show">PreReg5Requiered</Condition>
</Control>
</Dialog>
</UI>
</Fragment>
</Wix>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Language="1033"
Name="My WixToolset Example" Version="1.0.0" Manufacturer="KargWare"
UpgradeCode="{{INSERT-NEW-GUID-HERE}}">
...
<!-- UI-Dialogs -->
<UIRef Id="WixUI_KargWareFeatureTree"/>
<SetProperty Id="PreReg1FoundText" Value="Prerequisites 1" Before="AppSearch" />
<SetProperty Id="PREREG1CONDITION" Value="required" Sequence="ui" Before="LaunchConditions"><![CDATA[(1)]]></SetProperty>
<!--<SetProperty Id="PreReg2FoundText" Value="Prerequisites 2" Before="AppSearch" />
<SetProperty Id="PreReg3FoundText" Value="Prerequisites 3" Before="AppSearch" />
<SetProperty Id="PreReg4FoundText" Value="Prerequisites 4" Before="AppSearch" />
<SetProperty Id="PreReg5FoundText" Value="Prerequisites 5" Before="AppSearch" />-->
...
</Product>
...
</Wix>
<?xml version="1.0" encoding="utf-8"?>
<WixLocalization Culture="de-de" xmlns="http://schemas.microsoft.com/wix/2006/localization">
<String Id="PrerequisitesDlg_Title">[ProductName] Setup</String>
<String Id="PrerequisitesDlgBitmap">WixUI_Bmp_Banner</String>
<String Id="PrerequisitesDlgTitle">Voraussetzungen für [ProductName]</String>
<String Id="PrerequisitesDlgDescription">Liste und Status der Voraussetzungen.</String>
</WixLocalization>
<?xml version="1.0" encoding="utf-8"?>
<WixLocalization Culture="en-us" xmlns="http://schemas.microsoft.com/wix/2006/localization">
<String Id="PrerequisitesDlg_Title">[ProductName] Setup</String>
<String Id="PrerequisitesDlgBitmap">WixUI_Bmp_Banner</String>
<String Id="PrerequisitesDlgTitle">Prerequisites of [ProductName]</String>
<String Id="PrerequisitesDlgDescription">List and state of prerequisites. Install them manually or use the bootstrapper of [ProductName]</String>
</WixLocalization>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
<!--
First-time install dialog sequence:
- WixUI_WelcomeDlg
- PrerequisitesDlg (when needed)
- WixUI_LicenseAgreementDlg
- WixUI_CustomizeDlg
- WixUI_VerifyReadyDlg
- WixUI_DiskCostDlg
Maintenance dialog sequence:
- WixUI_MaintenanceWelcomeDlg
- WixUI_MaintenanceTypeDlg
- WixUI_CustomizeDlg
- WixUI_VerifyReadyDlg
Patch dialog sequence:
- WixUI_WelcomeDlg
- WixUI_VerifyReadyDlg
-->
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI Id="WixUI_KargWareFeatureTree">
<TextStyle Id="WixUI_Font_Normal" FaceName="Tahoma" Size="8" />
<TextStyle Id="WixUI_Font_Bigger" FaceName="Tahoma" Size="12" />
<TextStyle Id="WixUI_Font_Title" FaceName="Tahoma" Size="9" Bold="yes" />
<Property Id="DefaultUIFont" Value="WixUI_Font_Normal" />
<Property Id="WixUI_Mode" Value="FeatureTree" />
<DialogRef Id="ErrorDlg" />
<DialogRef Id="FatalError" />
<DialogRef Id="FilesInUse" />
<DialogRef Id="MsiRMFilesInUse" />
<DialogRef Id="PrepareDlg" />
<DialogRef Id="ProgressDlg" />
<DialogRef Id="ResumeDlg" />
<DialogRef Id="UserExit" />
<Publish Dialog="ExitDialog" Control="Finish" Event="EndDialog" Value="Return" Order="999"><![CDATA[1]]></Publish>
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="LicenseAgreementDlg"><![CDATA[(NOT Installed) AND NOT (PreReg1Requiered OR PreReg2Requiered OR PreReg3Requiered OR PreReg4Requiered OR PreReg5Requiered)]]></Publish>
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="PrerequisitesDlg"><![CDATA[(NOT Installed) AND (PreReg1Requiered OR PreReg2Requiered OR PreReg3Requiered OR PreReg4Requiered OR PreReg5Requiered)]]></Publish>
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg"><![CDATA[Installed AND PATCH]]></Publish>
<Publish Dialog="PrerequisitesDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg"><![CDATA[1]]></Publish>
<Publish Dialog="PrerequisitesDlg" Control="Next" Event="NewDialog" Value="LicenseAgreementDlg" Order="1"><![CDATA[1]]></Publish>
<Publish Dialog="LicenseAgreementDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg"><![CDATA[NOT (PreReg1Requiered OR PreReg2Requiered OR PreReg3Requiered OR PreReg4Requiered OR PreReg5Requiered)]]></Publish>
<Publish Dialog="LicenseAgreementDlg" Control="Back" Event="NewDialog" Value="PrerequisitesDlg"><![CDATA[(PreReg1Requiered OR PreReg2Requiered OR PreReg3Requiered OR PreReg4Requiered OR PreReg5Requiered)]]></Publish>
<Publish Dialog="LicenseAgreementDlg" Control="Next" Event="NewDialog" Value="CustomizeDlg"><![CDATA[LicenseAccepted = "1"]]></Publish>
<Publish Dialog="CustomizeDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="1"><![CDATA[Installed]]></Publish>
<Publish Dialog="CustomizeDlg" Control="Back" Event="NewDialog" Value="LicenseAgreementDlg" Order="2"><![CDATA[NOT Installed]]></Publish>
<Publish Dialog="CustomizeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg"><![CDATA[1]]></Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="CustomizeDlg" Order="1"><![CDATA[NOT Installed OR WixUI_InstallMode = "Change"]]></Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="2"><![CDATA[Installed AND NOT PATCH]]></Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="3"><![CDATA[Installed AND PATCH]]></Publish>
<Publish Dialog="MaintenanceWelcomeDlg" Control="Next" Event="NewDialog" Value="MaintenanceTypeDlg"><![CDATA[1]]></Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="ChangeButton" Event="NewDialog" Value="CustomizeDlg"><![CDATA[1]]></Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="RepairButton" Event="NewDialog" Value="VerifyReadyDlg"><![CDATA[1]]></Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="RemoveButton" Event="NewDialog" Value="VerifyReadyDlg"><![CDATA[1]]></Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="Back" Event="NewDialog" Value="MaintenanceWelcomeDlg"><![CDATA[1]]></Publish>
</UI>
<UIRef Id="WixUI_Common" />
</Fragment>
</Wix>
@RanKenig
Copy link

RanKenig commented Jun 9, 2022

Kudos on that!!!
I used your instructions to show DiskCostDlg in my setup.
Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment