This is a continuation of my last post regarding using Wix
3.7 with Visual Studio 2012. Previously I walked through the Wix tutorial (http://wix.tramontana.co.hu/tutorial/
) from “Getting Started” through “Putting it to Use”. In this post I want to
move into some of the User Interface and adding a custom dialog to the install
sequence.
First Steps
The first thing I did was add a Reference from my Wix
Installer Project to WixUIExtension library. You can find this in the bin
directory of the Wix Toolset installation folder. This will tell the linker (light)
to link in that library when you build the installer like running light.exe –ext
WixUIExtension Product.wixobj from the command line.
The tutorial had previously broken out the manual into a
separate feature, so I broke out the manual into a separate ComponentGroup and
broke out the Documentation feature from the MainProgram feature. We can give
the user the option to install either or both of these features now. I added
Title and Description fields for all the features. The Title is the name of the
feature the user will see in the installer treeview. The Description will
appear alongside the feature when the user clicks on it. As per the tutorial I
also added a Display=”expand” attribute and ConfigurableDirectory=”INSTALLFOLDER”
attribute to the Complete Feature. The first will have the tree item expanded
by default to show the two component features. The second attribute will allow
the user to select an install directory(??).
The tutorial sets the Level of the Documentation to 1000.
Since I don’t plan on using the “Mondo” UI, which includes the Typical, Custom
and Complete installation options, I don’t think this is really necessary but
will leave it. Anything with level 1-3 will be installed in a “Typical”
installation. Everything above 3 will be left out of a Typical install but can
be installed in the Custom and Complete options.
<Feature Id="Complete" Title='Foobar 1.0' Description='The complete package.'
Display='expand' Level='1' ConfigurableDirectory='INSTALLFOLDER'>
<Feature Id='MainProgram' Title='Program' Description='The main executable.' Level='1'>
<ComponentGroupRef Id="ProductComponents" />
<ComponentGroupRef Id="Shortcuts" />
</Feature>
<Feature Id='Documentation' Title='Documentation' Description='The instruction manual.' Level='1000'>
<ComponentGroupRef Id='DocumentationComponents' />
</Feature>
</Feature>
...
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="WixTutorial" />
</Directory>
<Directory Id="ProgramMenuFolder" Name="Programs">
<Directory Id="ProgramMenuDir" Name="Foobar 1.0" />
</Directory>
<Directory Id="DesktopFolder" Name="Desktop" />
</Directory>
</Fragment>
UI Wizardry
The next two lines that I added as children to the Product
element are all it takes to add some basic user interface to the installer. If
you went through the tramontana tutorial you saw the Mondo set of Wix UI. That
contains all the built-in UI features for Wix. The Feature Tree set contains
most of those screens but always assumes a Custom installation and allows the
user to select the features to be installed from the feature tree. The
ErrorProgressText extension uses Wix localized error and progress text rather
than the built-in Windows Installer messages.
<UIRef Id="WixUI_FeatureTree" />
<UIRef Id="WixUI_ErrorProgressText" />
In this setup scheme any feature that is not Level One will
show as not being installed by default as our Documentation feature shows
above. The figure also shows the “Browse. . .” button for the user to change
the installation directory if desired.
New Link in the Chain
Now we want to add a custom dialog into our setup sequence.
I start off by adding the new .wxs file by right-clicking on the Wix project
and doing Add > New Item > WiX > WiX File. I give the new file the
name UserRegistrationDlg.wxs. Now I have a Wix file with an empty fragment.
To this fragment I add a UI element with a single Dialog.
The Dialog attributes are fairly self-explanatory. The [ProductName] variable
will be replaced by the Name attribute of our Product element. The NoMinimize=”yes”
attribute indicates that the user cannot minimize the dialog. The dialog is
compsed of different Control elements of different types. Without going too much into designing new
dialogs, I want to point out the Edit type, MaskedEdit type, and PushButton
controls the new dialog has. The Edit type allows the user to input text that
is written to a property of the install session. In this case we have the
USERNAME and COMPANYNAME properties. The MaskedEdit allows the user to input
text in a specific format. We will specify the PIDTemplate in the main file.
The PushButton controls publish events. Primarily they are navigating back and
forth between different interface dialogs. Notice that the “Next” button will
also publish an event “ValidateProductID”. This event tells the installer to create a
ProductID with the input from the PIDKEY property if the key fits the format
specified by the template. Also a condition on moving to the Next dialog,
CustomizeDlg, is that the ProductID must exist. Thus, the user will not be able
to move to that dialog until they have input a proper PIDKEY. Later we’ll write
a custom action to handle this validation.
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="&User Name:" />
<Control Id="NameEdit" Type="Edit" X="45" Y="85" Width="220" Height="18" Property="USERNAME" Text="{80}" />
<Control Id="OrganizationLabel" Type="Text" X="45" Y="110" Width="100" Height="15" TabSkip="no" Text="&Organization:" />
<Control Id="OrganizationEdit" Type="Edit" X="45" Y="122" Width="220" Height="18" Property="COMPANYNAME" Text="{80}" />
<Control Id="CDKeyLabel" Type="Text" X="45" Y="147" Width="50" Height="10" TabSkip="no">
<Text>CD &Key:</Text>
</Control>
<Control Id="CDKeyEdit" Type="MaskedEdit" X="45" Y="159" Width="250" Height="16" Property="PIDKEY" Text="[PIDTemplate]" />
<Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="&Back">
<Publish Event="NewDialog" Value="LicenseAgreementDlg">1</Publish>
</Control>
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="&Next">
<Publish Event="ValidateProductID" Value="0">1</Publish>
<Publish Event="SpawnWaitDialog" Value="WaitForCostingDlg">CostingComplete = 1</Publish>
<Publish Event="NewDialog" Value="CustomizeDlg">ProductID</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 enter your customer information</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}Customer
Information</Text>
</Control>
<Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
</Dialog>
</UI>
</Fragment>
</Wix>
We next need to fit our dialog into the sequence of dialogs
in our UI. It should go between the LicenseAgreementDlg, specified in our “Back”
action, and the CustomizeDlg specified by the “Next” action. If you followed
the tutorial you will notice that I’ve traded the CustomizeDlg in for the
SetupTypeDlg that the tutorial uses. The CustomizeDlg is what the FeatureTree
uses, as we don’t allow the user to change the setup type as they can with the Mondo
UI.
In my product file I create a new UI container and move the
references to WixUI_FeatureTree and WixUI_ErrorProgressText to it. I also add
the DialogRef to the new dialog we created. Finally I add the Publish elements
that establish where to place our new dialog in the UI sequence. The Order
attribute gives a precedence to the publish events. Those with a higher number
will be fired before lower ones. Since the WixUI_FeatureTree set adds its own hooks to the buttons on the
builtin dialogs, we need to add order to our publish events for them to be
fired before the built-in events. The dialog reference (http://wix.sourceforge.net/manual-wix3/WixUI_dialog_reference_toc.htm)
explains the different built-in dialogs and what is included in each UI set.
Within the Fragment I also include the PIDTemplate property
as well as a property element for the PIDKEY property that tells the installer
not to log its value (Hidden=’yes’). Our property tells the user to enter 3
digits in each of two fields. In the Product element above I reference this UI
container. The MaskedEdit control and templates are explained here: http://msdn.microsoft.com/en-us/library/windows/desktop/aa369797(v=vs.85).aspx.
. . .
<UIRef Id="MyWixUI_FeatureTree" />
</Product>
. . .
<Fragment>
<UI Id="MyWixUI_FeatureTree">
<UIRef Id="WixUI_FeatureTree" />
<UIRef Id="WixUI_ErrorProgressText" />
<DialogRef Id="UserRegistrationDlg" />
<Publish Dialog="LicenseAgreementDlg" Control="Next" Event="NewDialog" Value="UserRegistrationDlg" Order="3">LicenseAccepted = "1"</Publish>
<Publish Dialog="CustomizeDlg" Control="Back" Event="NewDialog" Value="UserRegistrationDlg" Order="2">1</Publish>
</UI>
<Property Id="PIDTemplate"><![CDATA[12345<###
###>@@@@@]]></Property>
<Property Id="PIDKEY" Hidden='yes' />
</Fragment>
And with that you should be able to rebuild the installer and run
it. The Wix VisualStudio tool knows to compile and link both dialog files. You
should see our new dialog after the license agreement and see the key
validation working. Next we’ll walk through creating a custom action to do that
validation.
5 comments:
it is great post. You can also modify the default selections to have the rom that you want, with the minimum stock stuff. installerex custom installers
this is nice and great post.Hi I'm a web developer and i used this company installerex to build a custom installer , they build me a great and agile installer just the way i wanted , the installer is the fastest i saw , and now each time someone download my product online the installer install the program in the user computer
this is nice and great post.Hi I'm a web developer and i used this company installerex to build a custom installer , they build me a great and agile installer just the way i wanted , the installer is the fastest i saw , and now each time someone download my product online the installer install the program in the user compute installerex
Thank you so much for sharing this informative and useful post !!!!
I am getting a lot of errors when trying to build
"Entity 'User' not defined" and "Expecting ';'" etc.
Can you advise please?
Post a Comment