How to set product code of Wix bootstrapper install - wix

I'm using a bootstrapper to check for the existence and if needed install a set of 3rd party product installs. It then installs my product. I would like to include an uninstall shortcut for the full install and not just my product. However, to do that, I need to be able to set the product code for the bootstrapper and then reference it in my uninstall shortcut:
<ShortcutId="UninstallShortcut" Name="Uninstall My Product"
Description="Uninstalls My Product"Target="[System64Folder]msiexec.exe"
Arguments="/x [MyBootStrapperProductCode]" Icon="MainApp.ico"/>
I'm using the standard Wix bootstrapper, but I don't see anything within the Bundle element that will let me set the product code.
Alternately, can I prevent the bootstrapper from leaving references to itself in Add/Remove Programs? The 3rd party components are permanent deployments.

The Bundle doesn't work the same way as Product. It does not use msiexec to unistall, atleast not publicly.
In order to create UNISTALL shortcut for BUNDLE, you need some clever tricks. Disclaimer: only for developmental/internal use.
First; you need to pass UpgradeCode to your MSI, using this approach:
Passing command line args to MSI from WiX bundle
After that, in your MSI file, you could try searching registry value BundleUpgradeCode which equals to your UpgradeCode. If you have found the folder where value lies, you can extract UnistallString and execute it directly(using CustomAction).
It will be something like this: "C:\ProgramData\Package Cache{my GUID}\ExchangeBootStrapper.exe" /uninstall
I personally haven't implemented it yet, but couldn't find any other workaround for this problem and came up with this one.

I am late, but at least for the record. As I understand the products in the Chain of Burn are handled independently. So the uninstalls does. It means that you don't need the code for the whole bundle. Codes of the individual Msi files in the bundle chain will be used for the un-installation. As for permanent installation of 3d parties there is corresponding Permanent attribute. This all is quite well described in last two chapters of WiX 3.6 Guide by Ramirez N.

Related

Making changes to installed MSI

I will try to explain the issue by example. I have mypackage-v1.0.msi and mypackage-v1.1.msi. Both packages when installed silently expecting PASSWORD parameter:
msiexec /i mypackage-v1.0.msi /qb PASSWORD=SomeThing1
mypackage-v1.0.msi is already installed and mypackage-v1.1.msi should upgrade mypackage-v1.0.msi. There is a custom action in both packages that depends on this parameter but because of the issue with conditioning this custom action in mypackage-v1.0.msi, during upgrade it is executed but the PASSWORD parameter is not transferred to it.
I wonder if there is a way to patch mypackage-v1.0.msi before upgrading to mypackage-v1.1.msi. But the patch is not changing any contents of installation but the package itself. Is it possible?
Edit:
More focused input - is it possible with the patch to replace a condition for InstallExecuteSequence custom actions?
Yes. Patches include transforms, which modify packages. In fact, patches always modify tables in the package, even when they don't change content of the payload files.
The comments above became too messy. Here is a quick re-write as a regular answer:
Minor Upgrade: A minor upgrade can change most things in an installed MSI package before its uninstall or upgrade sequence is called. It can hence fix problems relating to major upgrades or failed uninstalls among other things (you fix the uninstall sequence before it is invoked).
Sample: Here is the simplest sample of a minor upgrade I could find at the moment (another sample from FireGiant's documentation).
For the simple sample: open the CreatePatch.cmd and update path to WiX binaries (likely ending in v3.11 at this point in time: set wixDir="C:\Program Files (x86)\WiX Toolset v3.11\bin\").
Keep in mind that a minor upgrade has many limitations. Keep things simple and change only what you need to fix your problem.
Minor Upgrade Details: The table at the bottom here shows what needs to change for a minor upgrade. Essentially package code and product version + plus whatever change you want to implement. The above link is to InstallShield's documentation (a different MSI tool), but this is a generic MSI technology concept - it is not vendor specific.
You can deliver the minor upgrade as a new MSI or as a patch file (*.msp). For an MSI you need to use a special command line to install. Something like this:
msiexec.exe /i MySetup.msi REINSTALLMODE=vomus REINSTALL=ALL
The v tells msiexec to re-cache the MSI so that it updates the existing cached one "in-place".
REINSTALLMODE documentation.
Applying Small Updates by Reinstalling the Product.
Links:
https://support.firegiant.com/hc/en-us/articles/230912367-Upgrade-options
https://www.firegiant.com/wix/tutorial/upgrades-and-modularization/

MSI Reinstall Issue with Specified Account already Exists error

We have 2 installer sources in WiX to create installer for a single product with same Product Version, GUID and Package GUID also.
Those 2 installer projects will yield different outputs, one output being just a single MSI file (File1.msi) and other project output is a CD-ROM structure having different MSI file name (File2.msi).
So now issue arises when we installed the product using single MSI file, upon that if we invoke MSI from the other CD-ROM output, we end up getting below mentioned error.
I tried keeping same MSI filename for both kind of installer output, then this above error dialog was resolved but repair functionality isn't working.
If some files were deleted in the product's destination folder, it says source file not found error pointing to CD-ROM installer source folder.
Please help where I'm going wrong. I want to support Repair installation without this errors.
The dialog is expected. You can't change the name of the MSI except during major upgrades.
After that, if you rebuilt to create the different layouts, each MSI probably has a unique PackageCode and that makes them unique packages. That is most likely why repair isn't working. A verbose log file should tell all.
Updated: Compile your main MSI, then run administrative image on it and put the extracted files and MSI on the CD? Put the compressed
version on there as well - just in case they prefer that kind of
release (happens).
I am not sure what will happen when you run both setups this way, but
I think the MSI flagged as an administrative image extract might be
detected by the engine. I am not sure. Should work. Built-in approach for MSI, and you are not fighting wind-mills.
User Accounts: Are you creating any NT User Accounts? Did you set the FailIfExists attribute to yes? Please check here:
User Element (Util Extension). What is the setting for UpdateIfExists? (if any).
Other Issues: There might be other issues as well as Rob mentions. You can not use the same package code for both release types because a package code by definition identifies a unique file. All kinds of X-Files-like problems occur if you try to "hack" this. Not a fight you want to take on.
Administrative Installation: Why would you want to distribute different setups on CDs these days? Corporations that use your setup will run an administrative installation on your setup extracting all files - which is a much better concept. It is essentially a glorified file-extraction, and it is a built in Windows Installer concept intended to make a network installation point for software - among other things. It essentially extracts all files and translates the Media table to use external source files.
List of Links:
What is the purpose of administrative installation initiated using msiexec /a?
Extract MSI from EXE

WiX 3.8 keeping config file state during Major Upgrade

I'm using WiX 3.8 (the latest stable release, I think), and I can't seem to get a config file to not get uninstalled-and-reinstalled during a major upgrade.
There are lots of questions about this on SO -- a lot of answers point to this site as a good answer. However, the suggestion given doesn't work (for me).
What the site says is to place each config file in its own component and mark the file as the key path of the component. Something like this:
<Component Id="config.xml"
Guid="*"
Directory="folder_where_config_file_lives">
<File Id="config_file"
Source="$(var.Project.ProjectDir)bin\Release\configFile.xml"
KeyPath="yes"/>
</Component>
Great. Next it says to schedule RemoveExistingProduct after the InstallFiles action, like so:
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallFiles"/>
</InstallExecuteSequence>
Problem is, when I compile, I get this error:
The InstallExecuteSequence table contains an action
'RemoveExistingProducts' that is declared in two different locations.
Please remove one of the actions or set the Overridable='yes'
attribute on one of their elements.
This person also had that problem, but he seems to have solved it. What fixed it for him was adding a scheduling attribute to the , which effectively got rid of the "two different locations" declaration problem (I guess):
<MajorUpgrade Schedule="afterInstallInitialize"
DowngradeErrorMessage="A newer version of [ProductName] is already installed."/>
So when I substitute the schedule change attribute (which contains a attribute itself, I guess), not only does it not work -- the config file gets removed and replaced during the upgrade -- it causes even more weirdness. My project has a bootstrapper with a lot of MSIs, and although I get log files for the installation of all of the MSIs that are after the MSI that contains the config file, they aren't installed.
Let me repeat that: the logs say that the MSIs are installed, but they aren't. There's probably a rollback somewhere that I can't find in the log files, but reading the MSI log files it looks like the installation went swimminly.
Does anyone know a way for a config file to not be removed-and-reinstalled during a Major Upgrade in Wix 3.8? What I've mentioned above is the best info from the interwebs that I could find, but I've tried pretty much everything on SO to no avail.
The MajorUpgrade element has everything you need, including where the RemoveExistingProducts action is scheduled. Don't add a RemoveExistingProducts into a sequence as well.
RemoveExistingProducts shouldn't be after InstallFiles. It's not clear where that comes from, but the documentation doesn't say that's a choice:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa371197(v=vs.85).aspx
When RemoveExistingProducts is sequenced early (such as after InstallInitialize or InstallValidate) it means that you are effectively uninstalling the old product followed by an install of the new product upgrade, and that means uninstalling the config file and installing the one in the upgrade. The way to retain the config file is to schedule REP afterInstallExecute. This results in an upgrade that is basically a version-rules install of the new product over the older installed one. The version rules mean that if you want updated binaries you must update their file versions. The good news about data files (your config file) is that updated data files won't be replaced:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa370531(v=vs.85).aspx
The older product then gets uninstalled, retaining the resulting set of files.
So sequencing of REP afterInstallExecute in the MajorUpgrade seems to be what you want. A caveat is that you need to follow component rules, which should happen automatically if you have auto-generated * guids in WiX.
IMO, Windows Installer was invented before XML caught on and the component rules don't handle it well. What I prefer to do is to not fight this behavior. Write your application so that one config file is owned by the installer and can always be safely overwritten and another config file that holds your user configuration data and that MSI doesn't know about. This second file should take override the first file.

How does Wix decide to install a particular file?

As I put in title, the question is how does Wix decide to install a particular file?
So I have exe file and when I change something in exe file and rebuild it, it will not get reinstalled if I don't change version. But if I change something in resource file, resource file will be replaced even if I don't change version of my application. So how wix is deciding if he need to replace file during upgrade or not.
I am using wix3.9. MajorUpgrade is schedule afterInstallFinalize.
Versioned files get replaced based on file version, yes, but data files get replaced based on whether you have specified file hash or not. I think WiX generates file hases by default, so this is the overwrite rule:
https://msdn.microsoft.com/en-us/library/aa370532(v=vs.85).aspx
and it's a Windows Installer rule that applies to all MSI settup, not a WiX decision.
P.S. afterInstallFinalize isn't an ideal place. afterInstallExecute is safer, and it will have the same overall result. The issue is that after InstallFinalize means that the new product is installed. If the uninstall of the older product then fails and rolls back you will end up with both old and new products installed, otherwise known as a mess. afterInstallExecute makes everything part of the transaction so you get the original product installed if there is a failure to uninstall it.

Removing the old bundle from ARP when upgrading SKUs

I'm deploying two CDs, and thinking both will have a setup.exe bundle.
One CD will be called "standard SKU" and setup.exe will install a.msi, and b.msi.
The other CD will be called "pro SKU" and setup.exe will install a.msi, b.msi, and c.msi.
What is the proper procedure when authoring the setup.exe files? Specifically, for the scenario where somebody installed the standard SKU, and then installed the pro SKU on top; would this be considered a related bundle/upgrade? Just install both bundles and keep both entries in ARP? Something else?
I wouldn't try to use upgrades here but related bundles is definitely the place to start. In this case, I would have the two Bundles share a RelatedBundle id and Tag them appropriately. Add something like the following to the "standard" Bundle:
<Bundle ... Tag='standard'>
<RelatedBundle Id='PUT-SAME-GUID-HERE' Action='Detect' />
Do the same for the "pro" Bundle but Tag it appropriately.
Now, in your custom bootstrapper application, on the OnDetectRelatedBundle() you'll get a callback when if one of the Bundles is already installed. That callback will also send back the Tag so you'll know which Bundle was present. You can display the result to the user or whatever if you like. The real important part is that during the OnPlanRelatedBundle() callback, you'll want to return the appropriate RequestState to say whether to remove or leave the found Bundle.
Good luck, all the data is there, just a matter of getting the right callbacks.