Skip to content

Instantly share code, notes, and snippets.

@hempnall
Last active June 1, 2020 16:48
Show Gist options
  • Save hempnall/ef86628a54c994b46e84b55796d25acb to your computer and use it in GitHub Desktop.
Save hempnall/ef86628a54c994b46e84b55796d25acb to your computer and use it in GitHub Desktop.
Wix Installer with GUI

Creating a Wix Installer with GUI

Within the <Product> tag, add a property

<Property Id='MOTTO' Value="The quick brown fox jumped over the lazy dog" />

The property name MUST be all upper case! Why is this?

This property will be used to edit an XML file:

<Component Id='Xml' Guid='C56A4180-574D-4A9A-A266-5B5EDDD022A4'>
  <File Id='Xml' Name='Sample.xml' DiskId='1' Source='Sample.xml' KeyPath='yes'/>
  <util:XmlFile Id="ModifyDataItem" Action="setValue" ElementPath="/sample/servername/@test" File="[INSTALLDIR]Sample.xml" Value="[MOTTO]"/>
</Component>

We add our own UI. We "raid" source code for Wix to borrow the "MinimalUI". We include this in our Wix compile and add a reference.

    <UIRef Id="MyMinimalUI"/>

We compile as follows:

candle .\SampleFirst.wxs .\MyWelcome.wxs  .\MyMinimal.wxs .\MuEula.wxs .\NewLink.wxs -ext WixUtilExtension
light .\SampleFirst.wixobj .\MyMinimal.wixobj .\MuEula.wixobj .\NewLink.wixobj .\MyWelcome.wixobj  -o SF.msi -ext WixUtilExtension -ext WixUIExtension

MyMinimal

MyMinimal is largely an exact copy of WixUI_Minimal.wxs from the Wix source code.

It has the following differences:

Give the new UI a name

Set the Id of the new UI.

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
        <UI Id="MyMinimalUI">
            <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" />

Add new Dialog References

We need to change the EULA dialog, because it will no longer install after you click "Install". Therefore we need a new box. Also, we need our new link in the chain

<DialogRef Id="MyWelcomeDlg" /> 
<DialogRef Id="MyWelcomeEulaDlg" />
<DialogRef Id="UserRegistrationDlg" />

We also need to add our new dialog to the install sequence

<InstallUISequence>
   <Show Dialog="MyWelcomeDlg" Before="MyWelcomeEulaDlg">Installed AND PATCH</Show> 
   <Show Dialog="MyWelcomeEulaDlg" Before="ProgressDlg">NOT Installed</Show> 
   <Show Dialog="UserRegistrationDlg"  Before="ProgressDlg"/> 
</InstallUISequence> 

We also need events:

<Publish Dialog="MyWelcomeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">Installed AND PATCH</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MyWelcomeDlg" Order="2">Installed AND PATCH</Publish>

The MyWelcomeDlg is never shown - why do we consider it here??

MyEula.wxs

This file is almost an exact copy of the EULA from Wix source code.

The following have been changed.

New name!

<UI>
 <Dialog Id="MyWelcomeEulaDlg" Width="370" Height="270" Title="!(loc.WelcomeEulaDlg_Title)">
 <Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="!(loc.WelcomeEulaDlgBitmap)" />          

Change LicenseAccept variable name

...
<Control Id="LicenseAcceptedCheckBox" Type="CheckBox" X="130" Y="207" Width="226" Height="18" CheckBoxValue="1" Property="MyLicenseAccepted" Text="!(loc.WelcomeEulaDlgLicenseAcceptedCheckBox)" />
...
<Control Id="Install">
 <Publish Event="EndDialog" Value="Return" Order="3">1</Publish>         
...
 <Condition Action="disable"><![CDATA[MyLicenseAccepted <> "1"]]></Condition>
 <Condition Action="enable">MyLicenseAccepted = "1"</Condition>
...
</Control>
                
<Control Id="InstallNoShield">
 <Publish Event="EndDialog" Value="Return" Order="3">1</Publish>    
...   
 <Condition Action="disable"><![CDATA[MyLicenseAccepted <> "1"]]></Condition>
 <Condition Action="enable">MyLicenseAccepted = "1"</Condition>
...
</Control>

Our new link

we have moved cost based conditions to this screen - they are no longer needed at the EULA stage. Is there a better way of doing this?

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
    <UI>

        <Dialog Id="UserRegistrationDlg" Width="370" Height="270" Title="[ProductName] Setup" NoMinimize="yes">
            <Control Id="NameLabel" Type="Text" X="45" Y="73" Width="100" Height="15" TabSkip="no" Text="Enter a motto:" />
            <Control Id="NameEdit" Type="Edit" X="45" Y="85" Width="220" Height="18" Property="MOTTO" Text="{80}" Indirect="no" />

                <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="Install">
                    <Publish Event="SpawnWaitDialog" Value="WaitForCostingDlg">!(wix.WixUICostingPopupOptOut) OR CostingComplete = 1</Publish>
                    <Publish Event="EndDialog" Value="Return"><![CDATA[OutOfDiskSpace <> 1]]></Publish>
                    <Publish Event="SpawnDialog" Value="OutOfRbDiskDlg">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND (PROMPTROLLBACKCOST="P" OR NOT PROMPTROLLBACKCOST)</Publish>
                    <Publish Event="EndDialog" Value="Return">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"</Publish>
                    <Publish Event="EnableRollback" Value="False">OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"</Publish>
                    <Publish Event="SpawnDialog" Value="OutOfDiskDlg">(OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 1) OR (OutOfDiskSpace = 1 AND PROMPTROLLBACKCOST="F")</Publish>
                </Control>
                <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="Cancel">
                    <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
                </Control>


                <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="WixUI_Bmp_Banner" />
                <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes">
                    <Text>Please configure your application</Text>
                </Control>
                <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
                <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes">
                    <Text>{\WixUI_Font_Title}Configuration</Text>
                </Control>
                <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />


            </Dialog>
        </UI>
    </Fragment>
</Wix>

Note the following:

<Control Id="NameEdit" Type="Edit" X="45" Y="85" Width="220" Height="18" Property="MOTTO" Text="{80}" Indirect="no" />

The text box will be automatically populated. We need Indirect="no" to write the contents of the text box back to the property

Can information we enter when not privileged by used when we are????

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