WIX UI - Creating a "passwords don't match" label - wix

I need my installer to accept a password, and so I've created a dialog on which users are prompted to enter their passwords twice (to avoid mistakes), however I'm having some trouble getting my "Your passwords don't match" label to appear and disappear at the correct times.
This is what I have so far:
<Control Id="Password" Type="Edit" Property="VDIR_PASSWORD" Password="yes" />
<Control Id="ConfirmPassword" Type="Edit" Property="ConfirmPassword" Password="yes" />
<Control Id="PasswordMismatchLabel" Type="Text" Text="Passwords do not match.">
<Condition Action="hide">VDIR_PASSWORD = ConfirmPassword</Condition>
</Control>
This compiles, however does the label never shows. (if I reverse the condition then the label shows, but doesn't disappear if they don't match).
I can see that the thing I'm missing is subscription to some event that updates the label whenever something happens (e.g. the user presses a key, or focus is lost from either of the controls), however I'm not able to find any documentation or examples of how I might achieve this.
Is it possible to do this?

Here is an example of what Yan is suggesting:
<Control Id="Next" Type="PushButton" X="238" Y="243" Width="56" Height="17" Text="Next">
<Publish Event="NewDialog" Value="VirtualDirectoryDlg">1</Publish>
<Condition Action="disable">
<![CDATA[(ACCOUNT_TYPE = "Service" AND WEB_APP_POOL_SERVICE_NAME = "") OR
(ACCOUNT_TYPE = "User" AND
((WEB_APP_POOL_IDENTITY_DOMAIN = "" OR
WEB_APP_POOL_IDENTITY_NAME = "" OR
WEB_APP_POOL_IDENTITY_PWD = "" OR
WEB_APP_POOL_IDENTITY_PWD_CONFIRM = "") OR (WEB_APP_POOL_IDENTITY_PWD <> WEB_APP_POOL_IDENTITY_PWD_CONFIRM))) ]]>
</Condition>
<Condition Action="enable">
<![CDATA[(ACCOUNT_TYPE = "Service" AND WEB_APP_POOL_SERVICE_NAME <> "") OR
(ACCOUNT_TYPE = "User" AND
((WEB_APP_POOL_IDENTITY_DOMAIN <> "" AND
WEB_APP_POOL_IDENTITY_NAME <> "" AND
WEB_APP_POOL_IDENTITY_PWD <> "" AND
WEB_APP_POOL_IDENTITY_PWD_CONFIRM <> "") AND (WEB_APP_POOL_IDENTITY_PWD = WEB_APP_POOL_IDENTITY_PWD_CONFIRM))) ]]>
</Condition>
</Control>

Here's the approach I took to solve this issue. This solution does not rely on disabling the "Next" button. Instead, it recognizes three states during the password comparison, but doesn't allow a user to proceed unless 1) both the password fields are populated, and 2) both password fields match. This solution also provides text labels to let the user better understand when there are errors states.
Hopefully this solution will help others.
The three states:
Passwords match
Passwords do not match
Passwords match, but are empty strings
Error states:
"Passwords do not match"
"Password fields required"
To get the red, slightly larger than normal text, by adding the following TextStyle element into my primary wxs file (e.g. product.wxs).
<UI>
<TextStyle Id="WixUI_Font_Large_Red" FaceName="Tahoma" Size="9" Red="255" />
</UI>
Here's the
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<Property Id="PASSWORD_COMPARE" Value="1" />
<UI>
<Dialog Id="ConfirmPasswordDlg" Width="370" Height="270" Title="Confirm Password Demo">
<Control Id="PasswdLabel" Type="Text" X="25" Y="65" Width="90" Height="15" TabSkip="no" Text="Password:" RightAligned="yes" />
<Control Id="PasswdEdit" Type="Edit" X="117" Y="62" Width="175" Height="16" Property="PASSWD" Text="{80}" Password="yes"></Control>
<Control Id="ConfirmPasswdLabel" Type="Text" X="25" Y="90" Width="90" Height="15" TabSkip="no" Text="Confirm Password:" RightAligned="yes" />
<Control Id="ConfirmPasswdEdit" Type="Edit" X="117" Y="87" Width="175" Height="16" Property="PASSWD_CONFIRM" Text="{80}" Password="yes"></Control>
<Control Id="PasswordsMatchLabel" Type="Text" X="150" Y="110" Width="140" Height="18" Text="{\WixUI_Font_Large_Red}Passwords do not match">
<Condition Action="hide">(PASSWORD_COMPARE = "1")</Condition>
<Condition Action="show">(PASSWORD_COMPARE = "2")</Condition>
<Condition Action="hide">(PASSWORD_COMPARE = "3")</Condition>
</Control>
<Control Id="PasswordsRequiredLabel" Type="Text" X="150" Y="110" Width="140" Height="18" Text="{\WixUI_Font_Large_Red}Password fields required">
<Condition Action="hide">(PASSWORD_COMPARE = "1")</Condition>
<Condition Action="hide">(PASSWORD_COMPARE = "2")</Condition>
<Condition Action="show">(PASSWORD_COMPARE = "3")</Condition>
</Control>
<Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="Back"></Control>
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="Next">
<Publish Property="PASSWORD_COMPARE" Value="1" Order="1">
<![CDATA[ (PASSWD = PASSWD_CONFIRM) ]]>
</Publish>
<Publish Property="PASSWORD_COMPARE" Value="2" Order="2">
<![CDATA[ (PASSWD <> PASSWD_CONFIRM) ]]>
</Publish>
<Publish Property="PASSWORD_COMPARE" Value="3" Order="3">
<![CDATA[ (PASSWD = "" AND PASSWD_CONFIRM = "") ]]>
</Publish>
<Publish Event="NewDialog" Value="VerifyReadyDlg" Order="4">PASSWORD_COMPARE = "1"</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>
</Dialog>
</UI>
</Fragment>
</Wix>

WiX can only do what underlying technology (Windows Installer) can. Windows Installer has poor UI comparing to usual desktop applications we all used to. So, answering your question: no, you can't show/hide the label based on the value you've typed into the password field. At least, I'm not aware about a supported way.
However, you can do the following. Drop that label, and instead add a condition to the Next button of this dialog. If passwords match, move to the next dialog in the chain. Otherwise, show a message box saying "password don't match" and stay on the current dialog until the user fills it in correctly.
Hope this helps.

As far as I'm aware, there is no event subscription model in Wix. What you'll likely have to do is create a custom action to verify that the passwords match and have that control the label. This may help also.

Related

WiX installer - Read from registry to checkbox value

I am fairly new to WiX and I got an issue where I cannot read a value from the registry to a Checkbox. I can read and populate to a ComboBox properly from the registry but for some reason the checkbox is not working.
Here is a part of my CustomUI.wxs
<Property Id="HEAPSIZEVALUE" Value="-Xms1024m" Secure="yes">
<RegistrySearch Id="RegHeapSizeValue" Type="raw" Root="HKCU"
Key="Software\Altair Semiconductor\!(loc.ProductName)" Name="Heap_Size" />
</Property>
<Property Id="POWERMODE" Value="1" Secure="yes">
<RegistrySearch Id="RegPowerModeValue" Type="raw" Root="HKCU"
Key="Software\Altair Semiconductor\!(loc.ProductName)" Name="Power" />
</Property>
<SetProperty Id="POWERMODE" Value="0" Before="InstallInitialize" Sequence="execute">NOT POWERMODE</SetProperty>
<UI Id="WixUI_MyMondo">
<Dialog Id="UserOptionsDialog" Width="370" Height="270" Title="Dialog Title">
<Control Id="TextLine2" Type="Text" X="50" Y="30" Width="250" Height="55" Text="Please choose the values for each of the following options (This can be skipped if typical options suffice)" TabSkip="yes" Transparent="yes" />
<Control Id="heapSizeLabel" Type="Text" X="50" Y="80" Height="17" Width="55" Transparent="yes" Text="Heap Size:" />
<Control Id="ComboBoxMain" Type="ComboBox" X="100" Y="79" Width="150" Height="20" Property="HEAPSIZEVALUE" >
<ComboBox Property="HEAPSIZEVALUE">
<ListItem Value="-Xms1024m" />
<ListItem Value="-Xms2048m" />
<ListItem Value="-Xms4096m" />
</ComboBox>
</Control>
<Control Id="PowerMode" Type="CheckBox" X="50" Y="100"
Width="290" Height="17" Property="POWERMODE"
CheckBoxValue="[POWERMODE]"
Text="Power (Allow device to sleep)" />
<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="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="Next" />
<Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="Back" />
</Dialog>
Here is my registry
My installer
As you can see my Heap_size field is read properly from the registry and shown to the user but for some reason the checbox is always shown as selected.
I went through the logs also and I see that the value is read properly from the registry
MSI (c) (08:24) [11:28:01:194]: PROPERTY CHANGE: Modifying POWERMODE property. Its current value is '1'. Its new value: '0'.
In Windows Installer, the CheckBoxValue field is the value of the property when the checkbox is selected not the property itself. When it's not selected it's null. So change it to CheckBoxValue="1".
Where it says Property="POWERMODE" this is the property that will control the checkbox. If it matches the value of CheckBoxValue then it'll be checked. If it's null it won't.
There is a wierd UI bug (feature?) in MSI that if you don't give CheckBoxValue a value then the control can't be checked and unchecked.
https://learn.microsoft.com/en-us/windows/win32/msi/checkbox-table
Remarks
If the check box is selected, then the corresponding property is set
to the specified value. If there is no value specified or this table
does not exist, then the property is set to its original value when
the check box is selected. If the original value is null, the property
is set to "1".
By the above logic an unspecified value causes the uncheck to set the property to 1 which then gets interpreted as checked causing the deadlock.

Wix Custom Action Property Not Immediately Available

I have a Wix VBScript Custom Action that sets a Property, and then a publish event that is supposed to trigger based on the value of the set property. The issue seems to be that the property is not being set and in turn not triggering the next publish event. Has anyone successfully done something similar?
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:hsi="http://schemas.hyland.com/wix/UtilityExtension">
<Fragment>
<Property Id="FOO" Value="0" Secure="yes" />
<CustomAction Id="Test3" Script="vbscript">
<![CDATA[
MsgBox Session.Property("FOO")
]]>
</CustomAction>
<CustomAction Id="Test2" Script="vbscript">
<![CDATA[
MsgBox "Test"
]]>
</CustomAction>
<CustomAction Id="Test1" Script="vbscript">
<![CDATA[
Session.Property("FOO") = "1"
]]>
</CustomAction>
</Fragment>
<Fragment>
<UI>
<DialogRef Id="WarningModalDlg"/>
<Dialog Id="BaseLawsonWebServerDlg" Width="370" Height="270" Title="Lawson LOB Broker Relay Setup">
<Control Id="label" Type="Text" X="20" Y="50" Width="200" Height="16" Text="Test" TabSkip="yes" Transparent="yes" />
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.WixUINext)">
<Publish Order="1" Event="DoAction" Value="Test3">1</Publish>
<Publish Order="2" Event="DoAction" Value="Test2">FOO = "1"</Publish>
<Publish Order="3" Event="DoAction" Value="Test1">1</Publish>
</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>
</Dialog>
</UI>
</Fragment>
</Wix>
Event="DoAction" Value="Test1" fires, I've tested it. Event="DoAction" Value="Test2">FOO = "1" does not hit. Then Event="DoAction" Value="Test3">1</Publish> definitely hits and shows the message box with the default value.
Thanks ahead of time!
I figured it out! I was so used to the reverse order of UI Dialog Publish events that I did the same thing for Control publish events.
Control Publish events move in the the order of 1 to x.
The publish events should look like this instead:
<Publish Order="1" Event="DoAction" Value="Test1">1</Publish>
<Publish Order="2" Event="DoAction" Value="Test2">FOO = "1"</Publish>
<Publish Order="3" Event="DoAction" Value="Test3">1</Publish>

WIX Popup dialog

I have two custom dialogs - dlg1 and dlg2. After user clicks NEXT on dlg1 another custom popup dialog with some text and OK button should be shown. After user clicks OK on this popup dlg2 should appear. I've tried a lot of things but the best of it just shows dlg2 on top of dlg1 and OK-popup.
You have to create a modal dialog which passes the user from the first dialog to the second. Actually modal dialogs are used to show a message and then return focus to the dialog in which the modal dialog was called. I don't know if you are breaking any installer rules, if you don't return focus to the calling dialog but it seems to work:
Code for dlg1:
<UI>
<Dialog Id="dlg1" ...>
<Control Id="firstText" Type="Text" X="10" Y="10" Width="200" Height="17" Text="First Dialog calls Modal Dialog." />
<Control Id="PopupButton" Type="PushButton" Text="Show Popup" Height="17" Width="56" X="100" Y="243" Default="yes">
<Publish Event="SpawnDialog" Value="PopupDlg" />
</Control>
</Dialog>
</UI>
Code for PopupDlg:
<UI>
<Dialog Id="PopupDlg" ...>
<Control Id="OkButton" Type="PushButton" Text="{\Tahoma_Bold}OK" Height="17" Width="56" X="200" Y="175">
<Publish Event="NewDialog" Value="dlg2" />
</Control>
</Dialog>
</UI>
Code for dlg2:
<UI>
<Dialog id="dlg2" ...>
<Control Id="secondText" Type="Text" X="10" Y="10" Width="200" Height="17" Text="Now proceed." />
<Control Id="CancelButton" Type="PushButton" Text="Cancel" Height="17" Width="56" X="180" Y="243">
<Publish Event="EndDialog" Value="Exit" />
</Control>
</Dialog>
</UI>
UPDATE
Implementing the solution above produces some problems. There is one workaround though, but it will render your code less readable. Let me first describe the concept behind the workaround before I post some code. Basically you are going to only have two dialogs: One which triggers the popup and the popup itself. In the popup, you do not open a new window, as described above, instead you return focus to the calling dialog. Additionally you change the state of a property. The calling dialog gets updated, based upon the property that has been set by the modal dialog.
To achieve this goal, you will have to add controls for each state in the calling dialog, one for the case the property has been set and one for the case the property has not been set.
Code for callingDialog:
<UI>
<Dialog Id="callingDialog" ...>
<Control Id="BeforePopup" Type="Text" X="10" Y="10" Width="200" Height="17" Text="Here is some text." Hidden="yes">
<Condition Action="show"><![CDATA[NOT PROP_SET_BY_MODAL_DLG]]></Condition>
<Condition Action="hide"><![CDATA[PROP_SET_BY_MODAL_DLG]]></Condition>
</Control>
<Control Id="AfterPopup" Type="Text" X="10" Y="10" Width="200" Height="17" Text="Popup was shown." Hidden="yes">
<Condition Action="show"><![CDATA[PROP_SET_BY_MODAL_DLG]]></Condition>
<Condition Action="hide"><![CDATA[NOT PROP_SET_BY_MODAL_DLG]]></Condition>
</Control>
<Control Id="PopupButton" Type="PushButton" Text="Show Popup" Height="17" Width="56" X="100" Y="243" Default="yes">
<Publish Event="SpawnDialog" Value="PopupDlg" />
</Control>
</Dialog>
</UI>
Code for PopupDlg:
<UI>
<Dialog Id="PopupDlg" ...>
<Control Id="OkButton" Type="PushButton" Text="OK" Height="17" Width="56" X="200" Y="175">
<Publish Property="PROP_SET_BY_MODAL_DLG" Value="1" Order="1">1</Publish>
<Publish Event="EndDialog" Value="Return" Order="2">1</Publish>
</Control>
</Dialog>
</UI>
Found one more solution for this. It's to use WinForms dialogs from a custom action.
When user clicks NEXT button custom action is invoked:
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.WixUINext)">
<Publish Event="DoAction" Value="SomeAction">1</Publish>
</Control>
In this custom action you can call WinForm dialog. And don't forget to set the check for the silent install mode to make sure that the dialog will not be showed during silent install:
[CustomAction]
public static ActionResult SomeAction(Session session)
{
if(Int32.Parse(session["UILevel"]) > 3)
{
var result = MessageBox.Show("Do something?", "Popup dialog", MessageBoxButtons.YesNo);
session["SOMEPROP"] = result == DialogResult.Yes ? "True" : "False";
}
return ActionResult.Success;
}

WIX radio button group

I am stuck in doing with WIX radio group button,I want to know
Whether i can able to disable text box based on selection of WIX radio group button like mentioned in the image below.
And how is it possible to save selection of radio group button value.As i needed the selected radio box value and save in registry.
for registry is it possible to assign the 1st text box value based on this condition?
<Condition><![CDATA[if (RADIOGROUP=1)<Property Id="RADIOGROUP" Value="[TEXTBOX1]" />]]></Condition>
<RegistryKey Root="HKLM" Key="SOFTWARE\Company\Service" >
<RegistryValue Name="RADIOGROUP" Value="[RADIOGROUP]" Type="string" >
</RegistryKey>
Can anyone help me.
Assuming you have your Radio Button as following:
<RadioButtonGroup Property="SOME_PROPERTY">
<RadioButton Value="0" Text="disable / hide labels" />
<RadioButton Value="1" Text="enable / show labels" />
</RadioButtonGroup>
you can control visibility or availablility of other elements in the dialog by using Condition sub-element:
<Control Id="SomeLabel" Type="Text" Text="text:">
<Condition Action="disable"><![CDATA[SOME_PROPERTY <> "1"]]></Condition>
<Condition Action="enable"><![CDATA[SOME_PROPERTY = "1"]]></Condition>
</Control>
<Control Id="SomeLabel2" Type="Text" Text="text2:">
<Condition Action="hide">SOME_PROPERTY = "0"></Condition>
<Condition Action="show">SOME_PROPERTY = "1"></Condition>
</Control>
Following the request in comments, posting an example of updating property with values of Edit elements (some required control attributes are ommited for clarity):
<CustomAction Id="CA_SET_TO_A" Property="P" Value="[AA]" />
<CustomAction Id="CA_SET_TO_B" Property="P" Value="[BB]" />
<Dialog Id="MyDialog" Title="[ProductName] Setup">
<Control Id="Next" Type="PushButton" Default="yes" Text="!(loc.WixUINext)">
<Publish Event="DoAction" Value="CA_SET_TO_A">R="USE_A"</Publish>
<Publish Event="DoAction" Value="CA_SET_TO_B">R="USE_B"</Publish>
</Control>
<Control Id="MyRadioButton" Type="RadioButtonGroup" Property="R">
<RadioButtonGroup Property="R">
<RadioButton Value="USE_A" Text="Save text field 1" />
<RadioButton Value="USE_B" Text="Save text field 2" />
</RadioButtonGroup>
</Control>
<Control Id="A" Type="Edit" Property="AA" Text="{64}">
<Condition Action="disable">R="USE_B"</Condition>
<Condition Action="enable">R="USE_A"</Condition>
</Control>
<Control Id="B" Type="Edit" Property="BB" Text="{64}">
<Condition Action="disable">R="USE_A"</Condition>
<Condition Action="enable">R="USE_B"</Condition>
</Control>
</Dialog>

Using a WiX property from a browse dialog

I'm developing a setup project using WiX, and I have the following problem. I get a directory path from the user using the Browse dialog, and I need to put this path in web.config. The problem is that in web.config that puts the value in "WWWMain" and not the path chosen by the user.
This is my code:
Product.wxs
<Property Id="IISLOGDIRECTORY" Value="WWWMain" />
Dialog.wxs
<Control Id="IISLogDirectoryEdit" Type="PathEdit" X="45" Y="100" Width="220" Height="18" Disabled="yes" Property="IISLOGDIRECTORY" Indirect="yes" />
Installation.wxs
<util:XmlFile Id="ModifyIISLogDirectory"
Action="setValue"
Permanent="yes"
ElementPath="/configuration/appSettings/add[\[]#key='isslogdirectory'[\]]/#value"
File="[INSTALLLOCATION]Web\Web.config"
Value="[IISLOGDIRECTORY]"/>
Declare the variable in Dialog.wxs itself but after the control
Example
<Control Id="DiffBackUpEdit" Type="PathEdit" X="120" Y="157" Width="160" Height="18" Property="IISLOGDIRECTORY">
</Control>
<Control Id="Browse12" Type="PushButton" X="290" Y="157" Width="56" Height="17" Text="Browse">
<Publish Property="_BrowseProperty" Value="DIFFDBBACKUPLOC" Order="1">1</Publish>
<Publish Event="SpawnDialog" Value="BrowseDlg" Order="2">1</Publish>
</Control>
Then at bottom in same page after add
<Property Id="IISLOGDIRECTORY" Value="C:\Database\MDM"/>