Wix multi language MSI with properties - wix

there are concepts seen in the past for WIX multi language MSI.
All are based on compiling the MSI multiple (takes very long for us, more than 1 hour per MSI) times and merge the results again to one MSI.
I play around and come up with this idea. Basically, define properties as translation targets and use them later in the dialogs.
Define in product two custom actions to set the properties, one for german and one for english:
<CustomAction Id="ZTR_NEXT1" Property="ZTR_NEXT" Value="Weiter"/>
<CustomAction Id="ZTR_NEXT2" Property="ZTR_NEXT" Value="Next"/>
<InstallUISequence>
<Custom Action="ZTR_NEXT1" After='LaunchConditions' >UserLanguageID=1033</Custom>
<Custom Action="ZTR_NEXT2" After='LaunchConditions' >UserLanguageID=1031</Custom>
</InstallUISequence>
usage in the dialog:
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ZTR_NEXT]">
Of course, i have to to this for every text and so the custom action table will grow a bit.
Anyway the benefits are:
one time MSI compile/link
change language also with a language select dialog at startup
Please give me some feedback about this approach, maybe why we should not do this

Related

How to modify a feature installation in Wix with custom property

Wix newbie - but I expect that is apparent.
I am using a modified version of the WixUI FeatureTree extension for an application that basically just copies files to specific directories. The installation wants to copy or remove based on a checkbox selection.
I have a feature for each installation package. I'm creating properties for each option and using them as a condition for each feature, changing the feature level to 1 or 0.
<!--Features for REVIT v2020-->
<Feature Id="Product2020" Title="Performance Seating v2020" Level="1">
<Condition Level="1">
<![CDATA[REVIT2020SELECTED = "Selected"]]>
</Condition>
<Condition Level="0">
<![CDATA[REVIT2020SELECTED <> "Selected"]]>
</Condition>
<!--Reference to Components.wxs component list hard coded-->
<ComponentGroupRef Id="2020Components" />
</Feature>
In the UI, I set the state of the property at the checkbox.
<Control Id="cbRevit2020"
Type="CheckBox"
Property="REVIT2020SELECTED"
X="50"
Y="110"
Height="10"
Width="150"
CheckBoxValue="Selected"
Text="Revit 2020"/>
The installation runs as expected on first run - features are installed based on the checkbox selection. Uninstall also works fine. Modify, however, does nothing regardless of checkbox state. I haven't changed anything in the FeatureTree.wxs custom file other than referencing my custom CustomizeDlg file.
I found reference to the issue (I think) here - https://robmensching.com/blog/posts/2010/5/2/the-wix-toolsets-remember-property-pattern/ However, it's over 10 years old and seems overly complex for what I need to do.
Does someone have a better approach?
BTW - yes, I know this is solvable simply by using the FeatureTree element. This is purely a personal preference, as I'm not a fan of that user interface in this application.
Thank you for any assistance.
Issue solved after quite a bit of searching and am posting in case it helps anyone else.
This article describes my desire and offers a good description of what is going on. https://www.joyofsetup.com/2007/05/30/feature-conditions-and-ui/
I removed the condition from the feature and moved it into the dialog as a publish event under the Next button control.
<Control Id="Next" Type="PushButton" X="248" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.WixUINext)">
<Subscribe Event="SelectionNoItems" Attribute="Enabled" />
<Publish Event="AddLocal" Value="ALL">1</Publish>
<Publish Event="Remove" Value="PRODUCT2020">NOT REVIT2020SELECTED</Publish>
<Publish Event="Remove" Value="PRODUCT2021">NOT REVIT2021SELECTED</Publish>
<Publish Event="Remove" Value="PRODUCT2022">NOT REVIT2022SELECTED</Publish>
<Publish Event="Remove" Value="PRODUCTFAMILIES">NOT FAMILIESSELECTED</Publish>
I preset selections in the dialog based on install condition.
<SetProperty Id="REVIT2020SELECTED"
After="MigrateFeatureStates"
Value="Selected">
<![CDATA[REVIT2020INSTALLED AND (NOT Installed OR NOT !PRODUCT2020=2)]]>
</SetProperty>

How can I insert InstallDirDlg into a custom dialog sequence?

I construct installer with custom dialogs and want to set action for the Next button to go to the directory selection dialog. So I use this code:
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Next]">
<Publish Event="NewDialog" Value="InstallDirDlg">1</Publish>
</Control>
But the InstallDirDlg dialog is unknown here because I don't include WixUI_InstallDir schema.
So can I include it somehow or I should find the InstallDirDlg source and copy it to my .wxs?
(I try to modify the samples code SampleCustomUI7.wxs from the WiX tutorial).
I think you should refer to documentation, it has exactly this example in chapter "Customizing Built-in WixUI Dialog Sets", based on your "WixUI_InstallDir" UI type:
Inserting a custom dialog into a built-in dialog set

WIX CUSTOM ACTION CALL AFTER NEXT

How can I make a call to my Custom Action dll when I click on Next button? Currently what I am doing is given below:
<CustomAction Id="TestingAction" BinaryKey="BIN_CustomAction" DllEntry="TestValue" Execute="deferred" Return="check" />
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="&Next"></Control>
<Custom Action="TestingAction" After="Next"></Custom>
When I given After ="Next" which is my Next button i am getting error after building my application.
Unresolved reference to symbol 'WixAction:InstallUISequence/Next' in
section 'Product:*.
How to resolve is issue and can anyone help me how to make a call to CustomAction after i click on Next Button.
What you are trying to do is to schedule the deferred custom action to a certain sequence and run it after a custom action called Next, which obviously doesn't exist. You should go a totally different way to call custom action on button click.
Follow the steps below:
create a custom action. It must be immediate (execute='immediate') and should never ever change the state of the target system
author a Control element - the button you'd like to trigger the event
finally, author a Publish element as a child of the Control, which publishes the DoAction event
Here's a full sample from the WiX sources how to print EULA on a button click:
<Control Id="Print" Type="PushButton" X="88" Y="243" Width="56" Height="17" Text="!(loc.WixUIPrint)">
<Publish Event="DoAction" Value="WixUIPrintEula">1</Publish>
</Control>
Obviously, the Control element should be a child of Dialog element.
And the custom action is defined like this:
<CustomAction Id="WixUIPrintEula" BinaryKey="WixUIWixca" DllEntry="PrintEula" Return="ignore" Execute="immediate" />
Hope this helps.

WiX: Enable/disable button before changing focus

I just started working on an installer my company is creating and we are using WiX. During installation, we ask for the installer's name and email address. The "Next" button is disabled until both of those fields are no longer empty. However, the button doesn't become enabled until focus is changed from the last field edited. I would like to enable the button as soon as both fields have something in them. Here's what I've got so far:
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.WixUINext)">
<Condition Action="disable"><![CDATA[UNAME = "" OR EMAIL = ""]]></Condition>
<Condition Action="enable"><![CDATA[UNAME <> "" AND EMAIL <> ""]]></Condition>
</Control>
Any and all help will be greatly appreciated. Thank you.
This is not supported by Windows Installer. Control conditions are not evaluated as you type in an edit box.
A solution would be a dummy Validate button next to your edit box. The user can click it after typing in the edit box so the focus is changed and control conditions evaluated.
Another solution would be to use an external UI which evaluates control conditions as you type. Some commercial setup authoring tools have this feature built-in.

Including modified FilesInUse dialog in WIX project

I have a modified FilesInUse dialog. Just including it in project and changing reference in UI does not help - I get "ICE20: Standard Dialog: 'FilesInUse' not found in Dialog table" error when building installation project.
Browsing the Net I've found one advice - to supress ICE validation for ICE20. Well, building the project with such settings works fine, and the msi also works fine, but I'm not sure that's a good solution to the problem.
Another advice was to modify FilesInUse and remove WixUIExtension from references, but as far as I know this way I'll end up with copying all the needed dialog files to my project. This I'd like to avoid.
So, what can be done to include my custom FilesInUse in WIX project correctly?
You could use a custom FilesInUse Dialog in the following manner:
<Fragment>
<UI>
<Dialog Id="FilesInUse" Width="370" Height="270" Title="Your product name">
<Control Id="Retry" Type="PushButton" X="304" Y ="243" Width="56" Height="17" Text="Retry" Default="yes" Cancel="yes">
<Publish Event="EndDialog" Value="Retry">1</Publish>
</Control>
<Control Id="Ignore" Type="PushButton" X="235" Y ="243" Width="56" Height="17" Text="Ignore">
<Publish Event="EndDialog" Value="Ignore">1</Publish>
</Control>
<Control Id="Exit" Type="PushButton" X="235" Y ="243" Width="56" Height="17" Text="Exit">
<Publish Event="EndDialog" Value="Exit">1</Publish>
</Control>
<Control Id ="InUseFiles" Type="ListBox" Width="300" Height="150" X="30" Y ="60" Property="FileInUseProcess" Sorted="yes" TabSkip="yes" />
</Dialog>
</UI>
</Fragment>
You just have to reference this Dialog into your Custom InstallDialog with the tag
<DialogRef Id="FilesInUse" />
All the tags mentioned are part of the ICE20 Dialog Requierements
Hope this helps. Have a nice day.
OK, I just spent some time trying to figure out how to solve this problem.
Though there are some good references in suggested thread, I think the FilesInUse dialog is a bit more specific to customize, so I decided to write a more concrete solution to the problem.
See, the problem is that MSI uses the FilesInUse dialog automatically, so if you try to change it somehow, you get errors such as FilesInUse not existing in Dialog table or duplicate FilesInUse dialog in table if you are referencing your custom dialog from other files.
The solution I found working was not to use DialogRef to Wix's FilesInUse dialog at all, but to make my custom dialog in main UI file (Where I would normally put DialogRef to FilesInUse) and name it FilesInUse.
Hope this helps other people having the same problem.
One more wrinkle is that the custom FilesInUse dialog will not be displayed when clicking Uninstall in Programs and Features since the uninstall is run with UILevel 3, so only the built-in FilesInUse will be displayed.
To work around that include this in your product.wxs:
<Property Id="ARPNOREMOVE" Value="1" />
Then when users press the Change (or Modify) button in Programs and Features, the Maintenance dialog will have a Remove button they can use to uninstall, and that will show custom dialogs. Products like Visual Studio only have a Change/Modify button.
One more thing is that Apps and Features (Windows 10) will disable the Modify button if the Uninstall key doesn't have a ModifyPath setting. It should be set to
MsiExec.exe /I{<yourproductcode>}
Your bootstrapper will need to do this. Not sure if the MSI can set it.
If building on the command line: light.exe -sice:ICE20...
If working in Visual Studio: Right click your setup project, select "Properties", Select "Tool settings" on left side of screen, Add "ICE20" to the "Suppress Specific ICE validation:" edit box.
See the related question and answers here: WiX replace dialog
User Yan Sklyarenko answered on Mar 25 '11:
Couple of articles to help you:
WiX
Tutorial
Neil Sleightholm's
article
You should find all the info you need for your case there.
User Bob Arnson answered on Mar 25 '11:
See "Changing the UI sequence of a built-in dialog set" in the topic
"Customizing Built-in WixUI Dialog Sets" in WiX.chm.