How to perform validation on Wix UI Edit control - wix

How can i do validation on a wix Edit control and make the Next button be available only if user entered some string (cannot be empty)
<Property Id="BASEKITPATH" Value=" " />
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.WixUINext)">
<Condition Action="disable"><![CDATA[BASEKITPATH = " "]]></Condition>
<Condition Action="enable"><![CDATA[BASEKITPATH <> " "]]></Condition>
</Control>
With the above code, the Next button is becoming ReadOnly when the installer starts, but when i change the text the Next button nothing changes and the Next stays ReadOnly
What seems to be the problem

It's a known limitation of the underlying Windows Installer. It has scenarios like this where the ControlConditions won't work because they don't validate propreties that have changed while the UI is shown.
The typical work around is to use mutually exclusive ControlEvents. One to call SpawnDialog to display a validation error message and one to go to the next applicable dialog.

If somebody looks for example he can find it in the source code of Wix.
Open "WixUI_InstallDir.wxs" and check "InstallDirDlg" Dialog.
Sample from code:
<Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="LicenseAgreementDlg">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="SetTargetPath" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="DoAction" Value="WixUIValidatePath" Order="2">NOT WIXUI_DONTVALIDATEPATH</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="SpawnDialog" Value="InvalidDirDlg" Order="3"><![CDATA[NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID<>"1"]]></Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="4">WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID="1"</Publish>
<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Property="_BrowseProperty" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Event="SpawnDialog" Value="BrowseDlg" Order="2">1</Publish>
Check the "SpawnDialog" event.

Related

How to do a custom validation of a selected installation target folder with WiX?

Using WixUI_InstallDir I'm allowing the user to select a target directory for installing an add-in. After the user enters the directory, I would like to check if the chosen installation folder has a parent directory matching a certain name.
The folder of on the of the parents of the installation directory must be SPECIFIED_NAME:
C:/SPECIFIED_NAME/target --> okay
C:/SPECIFIED_NAME/foo/bar/target --> okay
C:/foo/bar/SPECIFIED_NAME/target --> okay
C:/Temp/target --> not okay
Is this possible using WiX 3.x?
You can't do this with pure WixUI_InstallDir, you need to add extra validation of WIXUI_INSTALLDIR property using custom action.
Declare in your code new property FOLDER_IS_OK. It will take values okay/not okay from your example.
Write custom action, which will validate WixUI_InstallDir and write the result to FOLDER_IS_OK. Some information about this: change installer properties in C# custom action
Something like that:
[CustomAction]
public static ActionResult MyPathValidation(Session session)
{
string installDir = session["WIXUI_INSTALLDIR"];
session["FOLDER_IS_OK"] = ValidateInstallDir(installDir);
return ActionResult.Success;
}
public string ValidateInstallDir(string dirName)
{
//TODO
}
Add this custom action to your code, like in Step 1 here: https://wixtoolset.org/documentation/manual/v3/wixdev/extensions/authoring_custom_actions.html
In Wix source code find file WixUI_InstallDir.wxs. Copy whole element <UI Id="WixUI_InstallDir">...</UI> to your code. Change Id value to MyWixUI_InstallDir and link that one in UIRef element in your project.
Edit original block of your MyWixUI_InstallDir
<Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="LicenseAgreementDlg">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="SetTargetPath" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="DoAction" Value="WixUIValidatePath" Order="2">NOT WIXUI_DONTVALIDATEPATH</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="SpawnDialog" Value="InvalidDirDlg" Order="3"><![CDATA[NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID<>"1"]]></Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="4">WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID="1"</Publish>
<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Property="_BrowseProperty" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Event="SpawnDialog" Value="BrowseDlg" Order="2">1</Publish>
To something like that:
<Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="LicenseAgreementDlg">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="SetTargetPath" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="DoAction" Value="WixUIValidatePath" Order="2">NOT WIXUI_DONTVALIDATEPATH</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="DoAction" Value="MyPathValidation" Order="3">NOT WIXUI_DONTVALIDATEPATH</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="SpawnDialog" Value="InvalidDirDlg" Order="4"><![CDATA[NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID<>"1"]]></Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="SpawnDialog" Value="InvalidDirDlg" Order="5">FOLDER_IS_OK<>"okay"</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="6">WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID="1"</Publish>
<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Property="_BrowseProperty" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Event="SpawnDialog" Value="BrowseDlg" Order="2">1</Publish>

'Change' mode of Maintenance Dlg in Wix is disabled

After the installation of the setup, when the user again launches the setup in Maintenance mode, the 'Change' button appears to be disabled. There is a line below this button saying MyTempService has no independently selectable features.
How do I enable it?
My WixUI_Temp.wxs
<Publish Dialog="MaintenanceTypeDlg" Control="ChangeButton" Event="NewDialog" Value="MyInstallDirDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="RepairButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="RemoveButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="Back" Event="NewDialog" Value="MaintenanceWelcomeDlg">1</Publish>
Check my answer here to see if you can include a default Wix GUI: https://stackoverflow.com/a/22799031/129130 . I can't test this using this machine, but worth a shot.

How to prevent installation exit dialog from showing when the user has uninstalled? [WiX]

I have made a custom exit dialog for my installer. The problem is that it is shown when the user uninstalls the program, when I would like the default uninstall exit dialog to be shown instead.
My installer code is viewable at Github. I think the relevant code is:
<Publish Dialog="KerkerkruipExitDialog" Control="Finish" Event="EndDialog" Value="Return" Order="999">1</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg">1</Publish>
<Publish Dialog="MaintenanceWelcomeDlg" Control="Next" Event="NewDialog" Value="MaintenanceTypeDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="RepairButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="RemoveButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="Back" Event="NewDialog" Value="MaintenanceWelcomeDlg">1</Publish>
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">Installed AND PATCH</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="2">Installed AND PATCH</Publish>
<InstallUISequence>
<Show Dialog="WelcomeDlg" Before="KerkerkruipWelcomeEulaDlg">Installed AND PATCH</Show>
<Show Dialog="KerkerkruipWelcomeEulaDlg" Before="ProgressDlg">NOT Installed</Show>
<Show Dialog="KerkerkruipExitDialog" OnExit="success" Overridable="yes" />
</InstallUISequence>
<AdminUISequence>
<Show Dialog="KerkerkruipExitDialog" OnExit="success" Overridable="yes" />
</AdminUISequence>
You can have only one exit dialog for success. MSI doesn't let you have different success exit dialogs for different operations like install or uninstall. From the MSI SDK:
Each termination flag (negative value) can be used with no more than one action. Multiple actions can have termination flags, but they must be different flags.

Two PathEdit dialogs in one MSI (error 2343 - Specified path is empty)

I am creating a WiX installer, and I want to allow the user to select the path of the installation directory as well as a data directory. I added two InstallDirDlg's to my code and named one Custom_Dir and the other Custom_DirData.
In Custom_DirData, instead of using the WIXUI_INSTALLDIR property, I use a DATALOCATION property, which is set at the beginning of the installation in an appsearch.
When I run the msi, the Custom_Dir works fine. However, when I get to the Custom_DirData dialog, as soon as I press browse or next, a 2343 error message pops up.
This is what it says in the log:
DEBUG: Error 2343: Specified path is empty.
I can see these properties being set earlier on in the log file:
PROPERTY CHANGE: Adding DATALOCATION property. Its value is 'C:\Remindex Local Data\'.
PROPERTY CHANGE: Adding _BrowseProperty property. Its value is 'C:\Remindex Local Data\'.
So I'm not quite sure what path it's talking about. Just in case you need some extra information, here are three relevant dialogs in the UI code:
<Publish Dialog="Custom_Dir" Control="Back" Event="NewDialog" Value="Custom_Setup">1</Publish>
<Publish Dialog="Custom_Dir" Control="Next" Event="SetTargetPath" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="Custom_Dir" Control="Next" Event="DoAction" Value="WixUIValidatePath" Order="2">NOT WIXUI_DONTVALIDATEPATH</Publish>
<Publish Dialog="Custom_Dir" Control="Next" Event="SpawnDialog" Value="InvalidDirDlg" Order="3"><![CDATA[NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID<>"1"]]></Publish>
<Publish Dialog="Custom_Dir" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="4"><![CDATA[(WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID="1") AND WixUI_InstallMode = "InstallRemote"]]></Publish>
<Publish Dialog="Custom_Dir" Control="Next" Event="NewDialog" Value="Custom_DirData" Order="5"><![CDATA[(WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID="1") AND WixUI_InstallMode = "InstallServer"]]></Publish>
<Publish Dialog="Custom_Dir" Control="ChangeFolder" Property="_BrowseProperty" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="Custom_Dir" Control="ChangeFolder" Event="SpawnDialog" Value="BrowseDlg" Order="2">1</Publish>
<Publish Dialog="Custom_DirData" Control="Back" Event="NewDialog" Value="Custom_Dir">1</Publish>
<Publish Dialog="Custom_DirData" Control="Next" Event="SetTargetPath" Value="[DATALOCATION]" Order="1">1</Publish>
<Publish Dialog="Custom_DirData" Control="Next" Event="DoAction" Value="WixUIValidatePath" Order="2">NOT WIXUI_DONTVALIDATEPATH</Publish>
<Publish Dialog="Custom_DirData" Control="Next" Event="SpawnDialog" Value="InvalidDirDlg" Order="3"><![CDATA[NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID<>"1"]]></Publish>
<Publish Dialog="Custom_DirData" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="4">WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID="1"</Publish>
<Publish Dialog="Custom_DirData" Control="ChangeFolder" Property="_BrowseProperty" Value="[DATALOCATION]" Order="1">1</Publish>
<Publish Dialog="Custom_DirData" Control="ChangeFolder" Event="SpawnDialog" Value="BrowseDlg" Order="2">1</Publish>
<Publish Dialog="BrowseDlg" Control="OK" Event="DoAction" Value="WixUIValidatePath" Order="3">1</Publish>
<Publish Dialog="BrowseDlg" Control="OK" Event="SpawnDialog" Value="InvalidDirDlg" Order="4"><![CDATA[WIXUI_INSTALLDIR_VALID<>"1"]]></Publish>
Any suggestions would be greatly appreciated.
My problem was the brackets around my [DATALOCATION] property. This is what it should look like:
<Publish Dialog="Custom_DirData" Control="Back" Event="NewDialog" Value="Custom_Dir">1</Publish>
<Publish Dialog="Custom_DirData" Control="Next" Event="SetTargetPath" Value="DATALOCATION" Order="1">1</Publish>
<Publish Dialog="Custom_DirData" Control="Next" Event="DoAction" Value="WixUIValidatePath" Order="2">NOT WIXUI_DONTVALIDATEPATH</Publish>
<Publish Dialog="Custom_DirData" Control="Next" Event="SpawnDialog" Value="InvalidDirDlg" Order="3"><![CDATA[NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID<>"1"]]></Publish>
<Publish Dialog="Custom_DirData" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="4">WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID="1"</Publish>
<Publish Dialog="Custom_DirData" Control="ChangeFolder" Property="_BrowseProperty" Value="DATALOCATION" Order="1">1</Publish>
<Publish Dialog="Custom_DirData" Control="ChangeFolder" Event="SpawnDialog" Value="BrowseDlg" Order="2">1</Publish>

New dialog in WiX, clicking Back skips the dialog

I'm newbie in WiX and trying to customize dialog queue by adding the new one. The new dialog's name is ServerChoice and the flow is:
SetupTypeDlg <-> Full or Typical <-> ServerChoice <-> VerifyReadyDlg
or
SetupTypeDlg <-> Custom <-> CustomizeDlg <-> ServerChoice <-> VerifyReadyDlg
The only problem is in the first case at VerifyReadyDlg. 'Back' takes me to SetupTypeDlg and skips ServerChoice although in the second flow it works as required.
Source:
<UI>
<DialogRef Id="ServerChoice" />
<Publish Dialog="SetupTypeDlg" Control="TypicalButton" Event="NewDialog" Value="ServerChoice">1</Publish>
<Publish Dialog="SetupTypeDlg" Control="CompleteButton" Event="NewDialog" Value="ServerChoice">1</Publish>
<Publish Dialog="CustomizeDlg" Control="Next" Event="NewDialog" Value="ServerChoice">1</Publish>
<Publish Dialog="ServerChoice" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="ServerChoice">1</Publish>
<Publish Dialog="ServerChoice" Control="Back" Event="NewDialog" Value="CustomizeDlg" Order="1">WixUI_InstallMode = "InstallCustom"</Publish>
<Publish Dialog="ServerChoice" Control="Back" Event="NewDialog" Value="SetupTypeDlg" Order="2">WixUI_InstallMode = "InstallTypical" OR WixUI_InstallMode = "InstallComplete"</Publish>
<Publish Dialog="ServerChoice" Control="Back" Event="NewDialog" Value="CustomizeDlg" Order="3">WixUI_InstallMode = "Change"</Publish>
<Publish Dialog="ServerChoice" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="4">WixUI_InstallMode = "Repair" OR WixUI_InstallMode = "Remove"</Publish>
</UI>
Some help for a newbie? :)
What type of UI are you referencing (Mondo?). This information is not present in your piece of code. I think daddyman's comment is right, you probably have multiple events for that Back button, since Mondo itself hooks its own 'handlers' on this button-click event.
I have created a custom UI dialog flow recently and my approach was not referencing WiXUI_Mondo at all. Instead of it, I created my own new UI based on Mondo source code (you have to check WiX sources). At the end I have this code (irrelevant code parts have been removed) and it works fine.
<Fragment>
<!-- this is based on the WixUI_Mondo dialog set -->
<UI Id="WixUI_MyNewUI">
<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="Mondo" />
<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="WelcomeDlg" Control="Next" Event="NewDialog" Value="CustomizeDlg">1</Publish>
<!-- we do not use the SetupTypeDlg which allows user to choose either Typical, Complete or Custom installation; this ensures InstallCustom schema is run -->
<Publish Dialog="WelcomeDlg" Control="Next" Property="WixUI_InstallMode" Value="InstallCustom" Order="2">1</Publish>
<Publish Dialog="CustomizeDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="2">WixUI_InstallMode = "InstallCustom"</Publish>
<Publish Dialog="CustomizeDlg" Control="Next" Event="NewDialog" Value="MyDlg1">1</Publish>
<Publish Dialog="MyDlg1" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="1">MY_CONDITION_PROPERTY = 0</Publish>
<Publish Dialog="MyDlg1" Control="Next" Event="NewDialog" Value="MyDlg2" Order="2">MY_CONDITION_PROPERTY = 1</Publish>
<Publish Dialog="MyDlg2" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="1" />
<Publish Dialog="MyDlg2" Control="Back" Event="NewDialog" Value="MyDlg1">1</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MyDlg1" Order="1">WixUI_InstallMode = "InstallCustom" and MY_CONDITION_PROPERTY = 0</Publish>
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MyDlg2" Order="2">WixUI_InstallMode = "InstallCustom" and MY_CONDITION_PROPERTY = 1</Publish>
</UI>
<UIRef Id="WixUI_Common" />
<UIRef Id="WixUI_ErrorProgressText" />
</Fragment>
I think from your fragment that you are trying to do it in a just UI section and I don't believe that is possible. Take a look here http://neilsleightholm.blogspot.com/2008/08/customised-uis-for-wix.html I think it should help.