WiX: Use Burn to recache broken MSI - wix

We have a busted MSI in production that needs to be fixed via msiexec /fv package.msi before it can be properly upgraded.
I was hopeful that we could wrap this procedure in Burn but this Q and response from Rob appears that it might not be possible.
I tried:
<Chain>
<MsiPackage SourceFile="fixed-package.msi">
<MsiProperty Name="REINSTALLMODE" Value="v"/>
</MsiPackage>
</Chain>
But nothing happened.
I only need REINSTALLMODE=v and not REINSTALLMODE=amus as mentioned in the linked question, so I'm not sure if that makes a difference. The broken package has bad conditions that prevents uninstall and upgrades and this new one fixes that.
Have things changed in Burn since May '13 that recaching an existing MSI is now possible?
Thanks

You can also do it with a custom action. Just have the MSI extracted as temporary file in the beginning of the install for the new version, then execute a custom action to recache it, after which continue the installation. This is how I have done it so far.
However, I don't know if Wix has support for temporary files like Advanced Installer does (which is our tool), so you might need to build a custom action for that too.

Related

Wix Installer: Bundled MsiPackage causing install bundle to attempt to run again?

I have the following very basic WIX 3.11 bundle defined at the minute and I have removed the execpackages that fire before the MSI is installed as the problem I'm about to describe only occurs with the MSIPackage command and the specific Third Party MSI I'm using.
<?xml version="1.0"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
<Bundle Name="ACME APP 32Bit" Manufacturer="ACME CORP" Version="1.0.0.0" UpgradeCode="0B736949-AE50-46B0-A534-42C9672FAF1F" IconSourceFile='..\Common Files\Images\icon.ico'>
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLargeLicense">
<bal:WixStandardBootstrapperApplication
LicenseFile="..\Common Files\Documents\EULA.rtf"
ShowVersion="yes"
LogoFile="..\Common Files\Images\logo-64x64.png"
LogoSideFile="..\Common Files\Images\logo-64x64.png"
/>
</BootstrapperApplicationRef>
<Chain>
<MsiPackage Id="TP32BIT" SourceFile="ThirdParty.msi" Visible="no" />
</Chain>
</Bundle>
</Wix>
What is happening is after the bundle deploys the MSI and whilst the Installation completed successfully dialog is present , the modify setup dialog again (repair uninstall cancel ).
It only appears to happen with the third party MSI that I need to install. I don't have control over this MSI and nor can I get support on changing from the manufacturer at this time.
I've replaced the MSI with another random product and it doesn't result in the same issue. Its deployed without effectively attempting to run the bundle installer again.
I've run the Third Party MSI from the command line and checked it's return code on instillation and it returns 0.
I'm baffled as to whats causing the installer to think it needs to run itself again on completion of this MSI. Non of the UUIDs are in conflict and I don't think there's anything wrong in my xml.
If anyone can shed some light onto this I'd appreciate it. Currently the only thing I can think of doing is attempting to deploy this specific MSI to the platform via a execpackage approach that runs the msiexec from command line but that completely negates the reason I'm using a bundle in the first place.
Thanks in advance.
I am a little bit confused reading this.
Does the problem manifest itself if you run ThirdParty.msi interactively with full setup GUI outside the Burn Bundle?
In other words a regular installation, that is not invoked via command line but run by double clicking the MSI and then clicking through the setup GUI.
I suppose it is possible that some fancy event in the setup complete dialog kicks off a custom action that does something crazy. Is this an MSI that we can take a look at? Can you provide a download location? (no promises though).
When the setup is run in silent mode, the GUI sequence does not run - which could explain why things work in silent mode - if this is indeed the case.
Turns out it's a known bug in WIX that is triggered by the 3rd Party MSI. github.com/wixtoolset/issues/issues/5266 This MSI can't be changed and has to deploy it's content using this mechanism. I've been able to create a work around to resolve the issue as the installer starts 2 new instances of Wix after the MSI completes so I'm tracking the process IDs and killing anything "unknown" –

WiX Installer: Modify installation to include package skipped on initial installation

I am building a WiX bundle installer with a managed bootstrapper application. Recently, I added a new MsiPackage that installs per-machine, but only installs if the user opts-in via checkbox. The user can modify the installation later from Programs and Features to install this package. This is the only per-machine package in the bundle. The rest are per-user. Allowing installation without elevated privileges is critical for us, which is why this per-machine package is optional. Requesting elevated privileges during modify is fine.
Originally, I configured the new package like so:
<MsiPackage Id="optional_package"
Cache="yes" Compressed="yes" Visible="no"
DisplayInternalUI="no"
SourceFile="..\Resources\OptionalPackage.msi" />
The problem with this configuration was that, if the package was not installed on first installation of the bundle, it would not be cached (Cache="yes" only caches if the package gets installed). If the user then tried to modify the installation to install this package, that operation would fail, since burn could not locate the source of OptionalPackage.msi. I was able to work around this problem by requesting that the package always be cached:
<MsiPackage Id="optional_package"
Cache="always" Compressed="yes" Visible="no"
DisplayInternalUI="no"
SourceFile="..\Resources\OptionalPackage.msi" />
This fixed the first issue, but produced a new problem. Since OptionalPackage.msi installs per-machine, burn tries to cache it in C:\ProgramData\Package Cache (per-machine cache) instead of in %LocalAppData%\Package Cache (per-user cache). There are two problems with this:
C:\ProgramData\Package Cache is a per-machine location, which requires elevated privileges. Since we always cache this new package, the user always needs elevated privileges to install.
During installation, no UAC dialog pops up requesting elevated privileges. Instead the installer fails because it is denied access to C:\ProgramData\Package Cache. Running as an administrator is a workaround.
I suspect #2 is a burn bug, since it should be asking for permission to access the per-machine cache. My question is, can I cache to a custom location? Is it possible to force burn to cache per-machine packages to the per-user folder? I do not see any configuration options to do so.
I tried to provide some context here in case there is a better way to do this. My overall goal is to allow the user to install packages via modify that were skipped on first installation. If there is a better way to do this, please inform me.
I resolved this issue, so I thought I'd post an answer here for others to find. I ended up working around the caching problem by downloading the option package on-demand, rather than caching it. Just set Compressed="no" and set a DownloadUrl.
<MsiPackage Id="optional_package"
Cache="yes" Compressed="no" Visible="no"
DisplayInternalUI="no"
SourceFile="..\Resources\OptionalPackage.msi"
DownloadUrl="https://example.com/download/OptionalPackage.msi" />
When the package needs to be installed, WiX will automatically download it. Keep in mind that the file defined by SourceFile and that defined by DownloadUrl must match exactly. WiX hashes the SourceFile and stores that in your installer. It hashes the file at DownloadUrl after downloading and will only install it if the hash matches.
This solution wasn't ideal because it requires an interned connection, but there was no other way to satisfy our requirements. Our main issue is that this .msi is a per-machine package and our installer is running per-user. We had a consultation with FireGiant and learned the answer to a few of my other questions above as well:
It is not possible to define the cache location for packages from
within the installer. This can be configured in Windows by a system
administrator for a user's local machine, but not by us in our
installer.
The fact that WiX did not request elevated privileges in the circumstance I described is indeed a bug in burn.

WiX - Allowing a *manual* uninstall of one msi to uninstall another msi that shares the same UpgradeCode (and not just during the MajorUpgrade)

I have a bootstrapper (C# windows forms applications) that trigger two different msi files consecutively out of its resource. The instance transforms between the msi are 'paired' such that one instance transform from the first msi shares an UpgradeCode with one instance tranform from the second msi; these are the pairs that are installed together via the bootstrapper.
The 'core' msi (the first msi that runs) includes the MajorUpgrade element such that when a higher-versioned 'core' msi is run, all related products with a lower version are first uninstalled - this includes the secondary program installed via the second msi since it uses the same UpgradeCode and is recognized as a related product. This is the behaviour I want so that's good, but if I uninstall the 'core' msi program manually via the control panel, it only installs that one. I'd like to get it to uninstall the secondary program as well, even if I manually uninstall the 'core' one.
Do I need to write a custom function that manually calls the uninstall of the secondary msi's program with the ProductCode? E.g., as per here:
Wix - uninstall different product
Or, can I explicitly schedule RemoveExistingProducts to be run for uninstalls? Something like:
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallFinalize">REMOVE</RemoveExistingProducts>
</InstallExecuteSequence>
Is that not possible because after InstallFinalize of the 'core' msi, it knows nothing about the secondary msi? Basically, I'm wondering if I can also use the RemoveExistingProducts standard action for the manual uninstall the case, like it's doing for the MajorUpgrade case.
Thanks so much in advance.
Unfortunately, the answer is no.
RemoveExistingProducts does not trigger during a maintenance operation.
You will certain lines in the log file which indicate that:
Skipping RemoveExistingProducts action: current configuration is maintenance mode or an uninstall
What you are trying to do is usually achieved by making use of a bootstrapper application.
Have you explored the bootstrapping feature of Wix called Burn?
Burn should be able to easily handle your requirement.
If using Burn is not an option for you, then i dont see any other option other than writing your own custom code to achieve this.
Hope this helps.

WiX Bootstrapper - Minor Upgrade

I have a bootstrapper which is built using Burn and installs a package which i have setup to allow for minor upgrades when i run the msi packages using REINSTALL=ALL REINSTALLMODE=vomus from the command prompt (as per this article in the WiX docs).
However currently trying to upgrade with the setup.exe returns the message "Another version of this product is already installed..."
How do i get the boosttrapper to upgrade it's packages?
According to this question from 2009 burn "will be able" do the work of starting the MSI in the appropriate mode can it do it now?
I have tried using the MsiProperty element like this:
<MsiPackage Id="PackageId" SourceFile="path\to\my.msi">
<MsiProperty Name="REINSTALL" Value="ALL"/>
<MsiProperty Name="REINSTALLMODE" Value="vomus"/>
</MsiPackage>
But that doesn't seem to do it. What have i Missed?
If you are doing a minor upgrade Burn will automatically detect that and
pass the right switches for you. If you are trying to force it Burn does not support that.

Bundling Apple's Windows Bonjour installer into our msi

I've been asked to bundle Apple's Bonjour installer into our own msi installer, so that Bonjour automatically gets installed alongside our software. Anyone done this before? It doesn't seem to be trivial, as an msi installer cannot include and kick off another one. I assume I'd need some kind of batch file to run the two installers sequentially?
You'll need to use a bootstrapper to chain the Bonjour install with your installer. If you are using WiX 3.6 or later, using Burn to create a package bundle is a good option.
I found the Bonjour installer by downloading the Bonjour SDK and opening it in 7-zip, though I'm sure installing the SDK would provide access to it as well.
The way I typically like to do this is to add a new source file to your setup project for each dependency package to keep that logic separate from the main application setup.
The Bonjour package can be listed as a remote payload to retrieve on the fly, or build it into your setup. In this case, it seems more likely to build it in (Compressed="yes"). If you need to add any extra dependencies related to bonjour or parameters to pass into it, you could define them here as well.
<Fragment>
<!-- if a web link actually exists, I didn't find it... -->
<?define BonjourWebLink = "http://path/to/Bonjour.msi"?>
<PackageGroup Id="BonjourWeb">
<MsiPackage Id="BonjourWeb"
Compressed="no"
DownloadUrl="$(var.BonjourWebLink)">
</MsiPackage>
</PackageGroup>
<PackageGroup Id="Bonjour">
<MsiPackage Id="Bonjour"
Compressed="yes"
SourceFile="path\to\Bonjour.msi"/>
</PackageGroup>
</Fragment>
In your main bundle you just need to add a reference to the correct package group.
<Chain>
<PackageGroupRef Id="Bonjour"/>
<MsiPackage SourceFile="path\to\YourProduct.msi"/>
</Chain>
Since Bonjour uses MSI instead of an executable, you don't need to do anything to detect whether it is present or not; Burn will handle that for you. Actually, since WiX harvests most of the information your bundle needs from the MSI, this might be overkill, and you could just put in the MsiPackage element in your chain directly.
Don't forget to carefully check Apple's terms for doing this.
This would be a bit more work, and is prone to issues with upgrading, but you can take the Bonjour MSI and decompile it using dark. Convert the decompiled MSI into a Merge module that can be included with your installer, and you will have a single install. I have done this with some driver installs in the past, and it is usually not that complicated.
You need a bootstrapper; there are several freely available out there, including one being developed in WiX called Burn.
Wix Burn is relatively stable now.I`m using Wix 3.8.
If you are allowed to redistribute Bonjour Installer,you can chain the installer in Wix Burn. You can even put a condition to specify Bonjour as prerequesite for your installer.If it is not present,then Bonjour will be deployed, else it can be skipped.
You can check this link for understanding Burn.
http://wixtoolset.org/documentation/manual/v3/bundle/