Patching an installation using a bundle oder msi? - installation

I have no experience in patching/upgrading an installation.
We have a wix bundle setup with a standard (wix-created) msi inside which is added to the bundle this way:
<MsiPackage SourceFile="MySetup.msi" Id="MySetupId" Cache="yes" DisplayInternalUI="no" SuppressSignatureVerification ="yes" Visible="no" >
so in Add/Remove software section there is the bundle shown, not the msi itself.
Both, the msi and the bundle, are signed.
Currently our released version is "2.1.0.BuildNumber".
The bundle.wxs has upgrade code A
The msi has product code B and upgrade code C.
Unfortunately this version contains a mean bug but we don't want to release "v2.2.0.BuildNumber" just because of this bug, but "2.1.1.BuildNumber", so we need a patch.
What is be best practise here? Should we just create a msp file described like here
http://wixtoolset.org/documentation/manual/v3/patching/wix_patching.html?
Will this break the relationship between the bundle and the msi? Will this patch be shown in Add/Remove programms section?
Or is there a possibility to use the bundle for a patch?
Goal is, that our customers just can install the patch without deinstalling the old version, but can deinstall the whole scope using the formerly released bundle.

My personal advice is do not create patches unless absolutely necessary. You avoid a lot of trouble. The main problem IMO is that patches do not fit well onto source control and CI. First, you are not able to automatically increase the build number and include it into version number - it must remain the same. Second, creating an msp patch requires the binaries from the previous build be present during the new build. In MS technology the previous msi should be present, in WiX technology you cited you will need *.wixpdb from the previous build. Third (or the first?), the patch is a one-time action which should not be automated for continuous execution by CI.
If the bundle does not include its packages into exe but download them, a new bundle version can download only changed packages so that installation time will be small. Otherwise you are out of luck.
You need to create an msp upgrade for your buggy msi. The upgrade may or may not change the msi version, but if it does then the version of msi will not match the version of the bundle. User does not see msi version anyway.
You can install msp directly. When the bundle is uninstalled, msp will be uninstalled too. I do not know whether the msp will be visible in ARP (msi is not visible).
You may create a patch bundle. This is an independent bundle with its own upgrade code. It will contain
<Bundle .... ParentName="Name of your main bundle"...>
<RelatedBundle Id="YourMainBundleUpgradeCode" Action="Patch" />
Include MspPackage with your msp into the Chain.
This bundle will be visible in Installed Updates as a child of "Name of your main bundle" and it will be uninstalled with the main bundle or when a new version of the main bundle is installed.
You will also need to include a Condition to prevent installation of patch bundle when the main bundle of this particular version is not installed. There is no documented API to detect bundles (although you may use a RegistrySearch), but you may do ProductSearch for particular version of your msi included in main bundle.
Note that a new release of the main bundle with the same version number will install in parallel (there will be two identical entries in ARP) and new release with greater version number will automatically uninstall previous release. Thus, you cannot make new release of the main bundle.

Related

Why is it possible to install two MSIs with the same upgrade code?

Building MSIs with WixSharp since years, I always followed this rule which basically says:
For each new release of your application, change the ProductCode but never change the UpgradeCode.
This always worked perfectly but recently I discovered that installing a newer release of my application does not replace the previous version but instead is getting installed in parallel.
Running this PowerShell script gives me this result on a test machine:
My question
What is the reason that a MSI file does not replace an existing one upon installation with the same UpgradeCode?
(I've also posted this as a question on the WixSharp GitHub repository)
Update/solution
I've finally managed to solve it. Basically I did the following things:
Removed the version string from my setups name (since MSI seems to also compare then names to check whether an upgrade is possible; only the same name seems to fit)
Changed my version number from 4 to 3 digits, as Christopher pointed out. I.e. I'm now incrementing e.g. "1.0.0" to "1.0.1" etc.
Added this code to my WixSharp ManagedProject instance:
InstallScope = InstallScope.perMachine,
MajorUpgradeStrategy = new MajorUpgradeStrategy
{
UpgradeVersions = VersionRange.OlderThanThis,
PreventDowngradingVersions = VersionRange.NewerThanThis,
NewerProductInstalledErrorMessage = "Newer version already installed.",
RemoveExistingProductAfter = Step.InstallInitialize
},
After these changes, an upgrade succeeded.
The constraint is ProductCode not UpgradeCode. Only 1 MSI per ProductCode can be installed. Attempting to do so again will be a maintenance operation, small update or minor update.
Many MSI can share an UpgradeCode. (Not a good practice though!) For example it's not required for you to author a Major Upgrade at all.
The usual cause here though is you must change the version number in the first three fields and each install must be in the same context (per-user and per-user or per-machine and per-machine). BTW that's another way to install the same ProductCode twice. One per-user and one per-machine. Again not a good practice.
Good:
1.0.0 → 1.0.1 FindRelated Products in the 1.0.1 MSI will see the 1.0.0 and tell RemoveExistingProducts to remove it.
1.0.0 → 1.0.0 or
1.0.0.0 → 1.0.0.1 Bad. FindRelated will see it as the same version and not remove it.

How can I find packages already installed on my computer that have a chocolatey equivalent?

I would like to replace as many packages on my computer with the corresponding chocolatey packages, so they can be upgrade automatically.
Is there a possibility to scan the installed Apps and point out which of them have a chocolatey equivalent?
Thanks a bunch!
Yes, but it's probably not what you want to hear.
You can do this with the Package Synchronization feature, but this feature requires a Chocolatey for Business license (C4B). Automatic Synchronization is a similarly named feature (all paid licenses have it), but this only removes packages for which the related software was uninstalled outside of Chocolatey.
With the free version, you will have to instead synchronize your package state manually.
Note: I don't recommend doing this for packages you don't maintain on the community feed. The likelihood of getting malware is low, but I'd be more concerned with a poor search term causing the wrong package to get installed instead, or accidentally installing a less "official" package maintained by someone who is not as diligent with updates or has abandoned the package.
However, this should be a perfectly safe procedure for packages you develop and maintain (and in reality you'll probably know all the package ids and versions anyways, so you'll skip straight to step 3). Doubly so if you are installing from a private feed you or your organization controls.
Query your installed programs from Windows. Take note of the version you have installed so you can install the correct version.
Do a package search for each one, recording the package ID for each one.
choco list --order-by-popularity --version VERSION should help you avoid less official or less maintained packages for the same software, and get you the correct package version. Top of the list is the most popular.
This is not perfect as some software really only gets installed by a single version of the package, but either self updates or pulls from a latest URL. In these cases the package version is not usually updated or accurate.
Install each software per package ID you have. Do this one command at a time so you can specify the correct version.
choco install -n skips running the installation PowerShell script so it effectively only "imports" the package for management without performing the install.

VS 2015 Installer project - Dependencies with older version Number than installed

I have an app that uses a VS 2015 installer project.
Our BONEHEAD vendor, ComponentOne, released a new version of several assemblies upon which my product depends.
Here's the rub:
Old DLL version: 4.1.20102...
New DLL Version: 4.0.20162...
The newer DLL at least have newer file dates than the older one.
Of course, the newer DLL fix real user problems brought about by the bugs in the C1 components since corrected.
While I can get to the correct DLL by having the end user fully uninstall the older version of my product and installing the newer version, this is unworkable because:
We have an auto-update function that phones home and checks for the latest patch and installs it to update prevoius version; and
Our customers are female, 60+ and cyberphobic.
The project already has the RemovePreviousVersions property set to true, and I was hoping that this did a complete uninstall silently. It does not; the six assemblies with the version error are not replaced. The DetectNewerInstalledVersion property is also set to true; I tried to install with False, and it has no effect.
I also tried to explicitly include all detected dependencies of the C1 assemblies and it has no effect.
Is there a way to force the install project to overwrite the assemblies as long as the file date is newer regardless of the wrongly-encoded version?
Edited to add the following:
I tried making a custom action to delete the offending assemblies before installing anything - it runs after the files are installed. :(
I tried InstallShield LE, only to find out that it could not discover the dependencies more than one level deep, and provided no convenient way to explicitly specify the dependencies. I also could find nothing that would let me say to overwrite the assemblies based on date or unconditionally.
Thanks for any help you can offer!
I found an effective workaround.
I already had RemovePreviousVersions set to true, so I changed the application's default folder by adding [ProductVersion] onto the end of the path.
What this accomplished was:
It deleted the old assemblies; and
It created the new assemblies in the new folder.
This solved the problem nicely. No setting REINSTALLMODE to amus; no brute force solutions.

WiX - Cancel upgrade if previous version is not same configuration (Debug/Release)

I'm having some issues with custom actions not working properly (and causing broken installations) when trying to install a Debug build on top of a Release build, or vice-versa. Therefore I'd like to prevent such upgrades completely, and force the user to manually uninstall first.
So far I have this:
<?if $(var.Configuration) = Debug?>
<?define DisallowUpgrade = "yes"?>
<?else?>
<?define DisallowUpgrade = "no"?>
<?endif?>
<MajorUpgrade Disallow="$(var.DisallowUpgrade)" ... />
This forces the user to always uninstall first when installing a Debug build (which is fine). However it does not stop a Release build from trying to upgrade over a Debug build. How can I do this?
Thanks!
P.S. As I was typing I just thought of increasing the version number for Debug builds -- say by adding 100 to it. This would work, but could lead to confusion with QA people, so I'd prefer a cleaner way.
Why would a "user" ever know what a debug / release build is? IMO a user should only ever see a release build.
I would suggest build debug MSI and release MSI as two different products (upgrade code and even destination directory if you want side by side installs ) and a debug can only upgrade a debug and a release can only upgrade a release and only release MSIs ever go out the door to customers.
And of course, the less custom actions the better. :)
Write $(var.Configuration) to the registry, use RegistrySearch to load it, and use Condition to compare what's in the registry with the current value of $(var.Configuration).

Detemining newer version of executable in Wix

We have a software that has couple of executables inside. One of the executables is Windows service, and it doesn't change that often, usually we release many updates to the main executable, but the service version is same inside installer.
When service is installed first time or upgraded with newer version, we need to run custom action. We managed to solve first install part, but we don't know how to determine that version we're installing now is newer than one that already exists. Sort of if(newver > oldver) run custom action.
Thank you in advance
- Jack
You can try using the upgrade rules of your package. More details here: How to implement WiX installer upgrade?
Rob Mensching (the second answer in the linked thread) shows an example for upgrade rules. You should first familiarize yourself with the Upgrade table and how upgrade rules work. There isn't an easy answer or a quick fix for this in WiX.
Basically, you should have 2 upgrade rules
the first sets a property when an older version is found
the second sets another property when a newer version is found
After that you can use the older versions property to condition your custom action. For example, if the property is named OLDERVERSIONFOUND the custom action condition can be:
OLDERVERSIONFOUND
or something like
OLDERVERSIONFOUND > "1.0.0"
Your best bet is to store the "service" version somewhere in the registry, search for that registry value during upgrade and run your CA if newver > oldver (and the CA should also update said registry value to newver)
Note that Custom Actions are (generally) an admission of failure. I always try to separate out the configuration portion of setup to a pre-install (for sysadmins doing deployment) or post-install (for interactive installations) step - often a separate executable.
Declarative installations with no custom actions are much more reliable - if you can figure out how to rewrite the service so that your custom action is no longer required, you'll be much better off in the long term (this doesn't help when you're under pressure to release now, but it's something to think of for future releases)

Resources