I am struggling to learn the wix toolset, and currently want to do something I should think would be very simple: change the color of the text displayed in the dialog boxes defined in the toolset.
I found a stackoverflow answer which said I could do this by customizing WixUI_Minimal (which is the dialog set I'm using), giving it a different ID, and referencing that ID in my main wix file. The customization would simply be to do this:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI Id="WixUI_Custom">
<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" Red="255" />
And the reference in my main wxs file would be changed to:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*"
Name="Lan History Manager"
Language="1033"
Version="0.5.0.0"
Manufacturer="Jump for Joy Software"
UpgradeCode="EB2D1FB0-A72E-466C-B12D-BCF84277E2DA">
<Package InstallerVersion="500"
Compressed="yes"
InstallScope="perMachine"
Manufacturer="Jump for Joy Software"
Description="Installs a tool for managing Windows File History backups to network shares"
Comments="(C) 2017 Mark A. Olbert all rights reserved"/>
<UIRef Id="WixUI_Custom"/>
Unfortunately, this does not work. When I compile the project, it generates dozens of errors, complaining about duplicate symbols, all of which appear to relate to other parts of the WixUI_Minimal "template" which I did not change.
I do not have any definition for WixUI_Minimal present in my project, and no references are made to WixUI_Minimal, so it shouldn't be dragging in the duplicate symbols.
But something obviously is.
Is there some other way of just changing the text color in the dialogs?
The WiXUI_* can only be extended and overridden in limited ways. To go where you want to go you pretty much have to take a copy of it and own it. Go to the WiX sources and find the files that define all of this in the UI Extension. Clone them into your project and eliminate the UI extension. Now you can go and change anything you want about it.
Alternatively you could also decide to go full silent in the MSI and do all your UI work in a burn bootstrapper theme and/or customer bootstrapper application.
Related
We have the code below for our Product.wxs.
When the installer is run we can see afterward that BackupFiles custom action runs, but RestoreFiles does not run as shown in the log file:
"Skipping action: RestoreFiles (condition is false)"
Why does BackupFiles, with same condition, run and RestoreFiles not run?
Has the OLDVERSIONFOUND been changed?
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:bal="http://schemas.microsoft.com/wix/BalExtension"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension" >
<Product Id="*" Name="My Product" Language="1033" Version="0.0.0.0" Manufacturer="MyCompany"
UpgradeCode="{B55B9CB0-BA28-4BB3-834B-6075AD5D45E4}">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<UIRef Id="WixUI_ErrorProgressText" />
<!-- Specify UI -->
<Property Id="WIXUI_INSTALLDIR" Value="INSTALL_FOLDER" />
<Property Id="RestoreFiles" Value="INSTALL_FOLDER" />
<Upgrade Id="{B55B9CB0-BA28-4BB3-834B-6075AD5D45E4}">
<UpgradeVersion Minimum="1.0.0"
IncludeMinimum="yes"
OnlyDetect="no"
Maximum="0.0.0.0"
IncludeMaximum="no"
Property="OLDVERSIONFOUND" />
</Upgrade>
<InstallExecuteSequence>
<Custom Action="BackupFiles" After="InstallValidate" >OLDVERSIONFOUND</Custom>
<Custom Action="SetRestoreFiles" Before="RestoreFiles" />
<Custom Action="RestoreFiles" After="InstallFiles" >OLDVERSIONFOUND></Custom>
<RemoveExistingProducts After="InstallInitialize" />
</InstallExecuteSequence>
</Wix>
Custom actions like these are not really recommended. They can be quite complicated to get right. See links towards the bottom on "settings preservation".
The short version is that settings files should never be installed, but created by the application from defaults or templates (then the setup will never interfere with them), or you can cloud all settings and retrieve on launch from a database. See here, section "cloud-style approaches".
Major Upgrades - Uninstall & Install: There is an important weirdness with major upgrades. You have to remember that you kick off the new installer, and then it will kick of the old installer's uninstall sequence as part of its own operation. Hence a major upgrade will run the uninstall sequence of your old setup and the install sequence of your new setup (potentially in different orders based on configuration of the major upgrade settings).
Counter-Intuitive Effects: This combined "install / uninstall" approach affects logic, conditioning, sequencing and also property values a great deal - and some changes are very counter-intuitive. In addition to two different versions running "at the same time" (or during the same operation), you must also keep in mind that the each installation / uninstallation sequence runs in two different modes: immediate (building execution script) and deferred (executing script executing). With poor conditioning the same custom action could run several times unexpectedly (including in the GUI sequence of the launched setup). Confusing. Debug using message boxes as described towards the bottom here.
Detailed Explanation: This complexity and the phenomenon of property values seemingly changing during installation is attempted explained in detail here: Run Wix Custom action only during uninstall and not during Major upgrade - please read that answer (dual source and all). I will look back later, it is too late for me to run tests tonight.
Throwing in some further links:
On settings preservation
Overview on settings preservation
"Property Debugger" - on how to test property values
"Property Debugger" - another version
I have created a patch (.msp) in Wix toolset and this Updating my project as I would expect.
However I am having trouble creating a second patch on top of this, and have a few questions I was hoping someone could help with.
1) When generating the transformation do I do this from the original unpatched .msi or from the .msi containing the fixes that would have been included in patch 1.
2) In my Patch.wxs - what process do I need to follow? Things I have tried including incrementing the media id, increasing the version number of the patch family? Maybe I need a whole new patch family? Do I need a new cabinet file?
3) How do I add this new patch to my bootstrapper? Simply adding another node causes multiple control panel entries.
I'm not sure what source code to provide, so if you need anymore let me know.
Patch.wxs:
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
<Patch AllowRemoval='no' Manufacturer='Test' DisplayName='Test' Description='Test'
Classification='Update'>
<Media Id='3' Cabinet='TestPatch.cab'>
<PatchBaseline Id='TestPatch'>
<Validate UpgradeCode='yes' ProductVersion='Update' ProductVersionOperator='LesserOrEqual' ProductId='yes' />
</PatchBaseline>
</Media>
<PatchFamilyRef Id='TestPatchFamily' />
<PatchFamily Id='TestPatchFamily' Version='2.0.0.0' Supersede='yes'>
<PropertyRef Id='ProductVersion' />
<ComponentRef Id='MainExecutable' />
</PatchFamily>
</Patch>
My Bundle.wxs in the Bootstrapper was fine, I had to add the
MinorUpdateTargetRTM="yes"
attribute to the Patch element.
Thank you to this post.
I'm new with WiX, and I'm trying to have my Bootstrapper launch my installed application when it completes. To accomplish this, I'm using
<Variable Name="LaunchTarget" Value="path_to_exe"/>
However, it is not easy for me to get the path to the executable. The reason for this is because I'm using <Chain> to install some pre-requisites and then an msi that actually installs my exe.
So to do this, the msi is writting the path to a known location in the registry, and then the bootstrapper reads it and uses it.
The problem is that when the bootstrapper reads the registry, the msi hasn't run yet, so it is unable to run the executable at the end.
Here's my WiX, if it helps:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Bundle Name="My Installation" UpgradeCode="a8964402-f3fc-4878-aafd-31ecda6b685e" Version="1.0.0.0">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
<bal:WixStandardBootstrapperApplication LicenseFile="EULA.rtf"
ThemeFile="theme.xml"
SuppressOptionsUI="yes" />
</BootstrapperApplicationRef>
<Chain>
<PackageGroupRef Id="NetFx40Redist"/>
<ExePackage Id="OpenSSL" SourceFile="pre-requesite.exe" />
<MsiPackage Id="myInstall" SourceFile="mySetup.msi" />
</Chain>
<util:RegistrySearch Root="HKLM"
Key="Software\myProgram"
Value="myEXEPath"
Variable="myEXEPath"
Result="value"
Format="raw" />
<Variable Name="LaunchTarget" Value="[myEXEPath]"/>
</Bundle>
</Wix>
So, in short, I'm trying to have the RegistrySearch run AFTER the MsiPackage installs. Can this be done? If not, what alternatives do I have?
As I side note, if I manually fill in the registry value before installation, everything works fine. This means that besides the order things are running in, everything is working fine.
RegistrySearches run during the Detect operation. Custom BAs could run Detect after Apply, but that's not really an option since you're using the WixStandardBootstrapperApplication.
Lucky for you, WiX v3.9 added support for running the LaunchTarget already elevated, with the requirement that the path to the target .exe be in the registry under HKLM. So you would do this:
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
<bal:WixStandardBootstrapperApplication LicenseFile="EULA.rtf"
ThemeFile="theme.xml"
SuppressOptionsUI="yes"
LaunchTargetElevatedId="MyAEEId" />
</BootstrapperApplicationRef>
<ApprovedExeForElevation Id="MyAEEId"
Key="Software\myProgram" Value="myEXEPath" />
Edit:
It looks like you are required to set LaunchTarget as well. Why doesn't your bundle know where it will be? You can just put in gibberish for LaunchTarget (WixStdBA will try the registry location first), but can't you use built-in variables and/or MsiProperty elements to locate the exe?
recently I'm working on creating a multilanguage wix msi package for my team. I searched the localization on Google and also on stackoverflow for quite some time and finally found something to follow:http://www.geektieguy.com/2010/03/13/create-a-multi-lingual-multi-language-msi-using-wix-and-custom-build-scripts/. Currently I just added 2 language support: english and simplified Chinese to check if this approach works for me. The main wxs front part is something like this:
<Product Id="B5CB3C6A-A8ED-4308-8ADE-17729FE1FB23" Name="MyProduct" Language="!(loc.LANG)" Codepage="UTF-8" Version="11.51.0027" Manufacturer="My Company" UpgradeCode="D42070C3-43CB-4E2B-9B96-2F8D84A6C8A8">
<Package InstallerVersion="200" Compressed="yes" Languages="1033,2052" InstallPrivileges="elevated" InstallScope="perMachine" />
And for the Language attribute of the Product I'm getting value from the localization wxl file, I've 2 files now, one is en-US.wxl, another is zh-CN.wxl,
in en-US.wxl: 1033
in zh-CN.wxl 2052
I also set the corresponding codepage in 2 wxl files, setting en-US codepage to 1252 and zh-CN to 936.
After building the project in VS, I got 2 msi, one in en-US folder and another in zh-CN folder, and I use the following commands to create the multilanguage msi:
cscript WiLangId.vbs zh-CN\MyProduct.msi Product 2052
Msitrans.exe -g en-US\MyProduct.msi zh-CN\MyProduct.msi zh-CN.mst
cscript WiSubStg.vbs en-US\MyProduct.msi zh-CN.mst 2052
cscript WiSubStg.vbs en-US\MyProduct.msi
And performing the commands above in cmd, I copied the final msi onto a Chinese win7 system to try, the problem is after I double clicking the msi to install, the first UI dialog is still in English but shortly it became Chinese, I'm sorry that I couldn't post the screenshot here because stackoverflow requires 10 reputations to be able to post images, but the words on the first Dialog I saw is "Preparing to install...." and a button on the bottom right "Cancel" and then after 2-3 seconds the UI became Chinese. Did anyone come up with this problem before?
Windows System restore point is created by default (if enabled system-wide) at the start of a MSI install. This system restore point seems to occur before locale transform and cause the behavior you observed.
You can disable it by setting MSIFASTINSTALL property to 1 or any value that includes it (e.g. 5 if you also want to reduce the amount of progress messages)
<Property Hidden="yes" Id="MSIFASTINSTALL" Value="1" />
For example in your .wxs file:
<?xml version="1.0" ?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util='http://schemas.microsoft.com/wix/UtilExtension'>
<Product Id="XXX" Name="XXX" Language='!(loc.LANG)' Codepage='0'
Version="XXX" Manufacturer="XXX"
UpgradeCode="XXX">
<Product Id="B5CB3C6A-A8ED-4308-8ADE-17729FE1FB23" Name="MyProduct" Language="!(loc.LANG)" Codepage="UTF-8" Version="11.51.0027" Manufacturer="My Company" UpgradeCode="D42070C3-43CB-4E2B-9B96-2F8D84A6C8A8">
<Package InstallerVersion="200" Compressed="yes" Languages="1033,2052" InstallPrivileges="elevated" InstallScope="perMachine" />
<!-- Disable System Restore point creation for this MSI (faster installation) -->
<Property Hidden="yes" Id="MSIFASTINSTALL" Value="1" />
<!-- Rest of your setup ... -->
</Product>
</Wix>
You can read about MSIFASTINSTALL on Microsoft Windows docs
I'm using an rtflicence standard bootstrapper to install dotnet before my poject msi in a chain.
I noticed that there's an 'options' button which displays an install location dialog and allows the user to change the default installation directory.
I need to either:
Prevent this options button from being displayed, or
Populate the install location with a default path, and pass this back to the installer should the user change it.
I read that it's possible to pass Burn variables to msipackages from bootstrapper but I haven't found any further details and would appreciate being pointed in the right direction.
Thanks
To go with option 1, you'd have to roll your own BootstrapperApplication and remove the options button from the menu.
Option two is significantly easier to implement. The bootstrapper uses a special Burn variable called InstallFolder to get and set what is in the text block on that view, which you can assign inside the Bundle element.
<Variable Name="InstallFolder" Type="string" Value="[ProgramFilesFolder]"/>
The constant ProgramFilesFolder will set the value of that text block when the program starts, and if the user browses to a different directory, it will be stored in that same variable. To pass it to the MSI, in your chain, you pass the InstallFolder using the MsiProperty tag (INSTALLLOCATION is the name of the property in your WiX project).
<MsiPackage Vital="yes" DisplayName="Your Name" Id="MsiId" SourceFile="path/to/file.msi">
<MsiProperty Name="INSTALLLOCATION" Value="[InstallFolder]" />
</MsiPackage>
I just discovered the SuppressOptionsUI option that addresses your Option 1 without rolling your own BootstrapperApplication:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
<Bundle>
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
<bal:WixStandardBootstrapperApplication LicenseFile="..\eula.rtf" SuppressOptionsUI="yes"/>
</BootstrapperApplicationRef>
<Chain>
</Chain>
</Bundle>
</Wix>
I think you can try removing the options button by creating a theme. I haven't had to use themes myself but here are two related SO links that may get you pointed in that direction:
WiX bootstrapper theme file?
Theme for my WiX Installer