Preventing Wix from installing All Features in my Product? - windows

After installing a MSP patch, Windows Installer decides to install ALL Features provided in the initial MSI. How can i prevent MSP patch from installing All available Features?
Features requests show like this:
Installed: Absent
Request: local
Action : local
Why is it requesting to install all?

I found out that the ADDLOCAL property was being set to all the Uninstalled Features. This caused a "Request: local" for each one. What i did to solve the issue was to use a small custom action that deletes this property. It needs to go before CostFinalize because the features to be installed need to be defined before that action.
The variable REINSTALL holds the features that are already installed, and all of them are requested for REINSTALL. So the MSP patch only REINSTALLs the already installed features and leaves the uninstalled features untouched.
<CustomAction Id="REMOVE_ADDLOCAL_PROPERTY"
Property="ADDLOCAL" Value="[NonExistentProperty]"
/>
<InstallExecuteSequence>
<Custom Action="REMOVE_ADDLOCAL_PROPERTY" Before="CostFinalize">
<![CDATA[PATCH]]>
</Custom>
</InstallExecuteSequence>
EDIT:
In the end, this solution worked for one of my patches, but failed for another. So the final solution i've implemented so far is to set REINSTALL=ALL during the Patch.This MSDN link stands that:
Note that even if REINSTALL is set to ALL, only those features that were already installed previously are reinstalled. Thus, if REINSTALL is set for a product that is yet to be installed, no installation action will take place at all.
so i think this is a better solution than removing the ADDLOCAL property. And also it worked for both patches.

You have to save the selected features to the registry upon initial installation, ADDLOCAL property. When installing the patch, it has to read the states from the registry setup ADDLOCAL property accordingly.
Otherwise the patch runs as if the defaults are selected, and therefore the missing features get installed.
You linked to a question for Upgrade case, MigrateFeatures attribute, which refers to MigrateFeatureStates action, does not work in case of patches.

Related

Patching an installation using a bundle oder msi?

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.

Wix - Run Custom Action only On Upgrade and Patch Not on Repair/Reinstall

I want to run a Wix custom action only on upgrade and patches and NOT install/reinstall or repair. So basically only if the version number of the application is increasing should this custom action run. I tried the following rule and it disabled the custom action completely on patching:
<Custom Action="upgrade_action"
Before="InstallFinalize">Installed AND NOT REMOVE AND UPGRADINGPRODUCTCODE</Custom>
What can I do to achieve this?
If this is the new major upgrade product and you are using the WiX MajorUpgrade element then the WIX_UPGRADE_DETECTED property is set if it's doing an upgrade and detecting an older version. UPGRADINGPRODUCTCODE is set in the old product being upgraded, the one that's already installed.
It looks like all you need is WIX_UPGRADE_DETECTED Or PATCH if you want the CA to run on either of those conditions only.

How to prevent installation if other product is already installed, using Wix

We have two different products that can't be both installed on the same machine without them breaking, so we need to add a check in the Wix installer for the first one, call that A, that prevents it from being installed on a machine that already has the other, say B, installed.
We already have different UpgradeCodes defined for A and B, but what do I need to add to the Wix install XML to say something like "if you find anything with UpgradeCode A, don't install this, since this has UpgradeCode B".
I've seen similar questions here but the answers don't usually provide clear xml, and are only partially similar, such as checking for x86 vs 64 of the same product or just prevent installation of an older version of the same product, which we already do. Almost all of the Wix answers on here don't actually contain xml, which I find weird, since that's the only way I know of how to define these things.
The Wix documentation on this was also pretty sparse, I found something about AppSearch (http://wixtoolset.org/documentation/manual/v3/xsd/wix/appsearch.html) but that doesn't help me in figuring out how to use that in the xml to prevent the installation if the app is found, or how to search for it by the UpgradeCode or differently somehow.
You should be able to add some upgrade detection in product A:
<Upgrade Id="$(var.ProductBInstallerUpgradeGUID)" >
<UpgradeVersion
IncludeMaximum ="yes"
IncludeMinimum="yes"
Maximum="255.255.65535.65535"
Minimum="1.0.0.0"
MigrateFeatures="no"
Property="PRODUCTBISINSTALLED"
OnlyDetect="yes" />
</Upgrade>
then you can use a launch condition
<Condition Message="!(loc.CannotInstallWithProductBInstalled)">NOT PRODUCTBISINSTALLED OR Installed</Condition>
So if product b is detected on this machine, it will stop the install with the error message that is defined by the "CannotInstallWithProductBInstalled" string in the localization file.
Similarly for Product A detection in product B
You can search for a component id from the other installed product with a Property declaration that includes a componentsearch, like the examples here with Property id and ComponentSearch:
How to check for installed package in WiX 3.0?
Then use the property in a launch condition.
UpgradeCode detection works most of the time, but won't work cross-context. If the previous product was installed per machine (or per user) and yours is the opposite then it won't be detected by an upgrade search. Assuming that all the installs are the same and specified in InstallScope, then an UpgradeSearch will be fine.

ADDLOCAL property getting set during a PATCH

I have an MSI package which installs many features that the user can select for installing in his computer. I also have an MSP patch package that updates some components and fixes some bugs in the application. I noticed that during the Patch installation, the property ADDLOCAL gets automatically set to a list containing all the features(during CostFinalize action).
I'd like to know why the "CostFinalize" action is setting ADDLOCAL property and why is it setting it with all the "absent" features.
My problem is that the Patch is installing EVERYTHING.
I really can't find an explanation to this so any help will be greatly appreciated.
Edit:
Link to same issue: here
You already tried to solve this problem. That time, you found out that REINSTALL property holds the features which were installed by the user.
Then the simple trick of assigning this value to ADDLOCAL should help:
<CustomAction Id="CopyReinstallToADDLOCAL"
Property="ADDLOCAL" Value="[REINSTALL]"
/>
<InstallExecuteSequence>
<Custom Action="RCopyReinstallToADDLOCAL" Before="CostFinalize">
<![CDATA[PATCH]]>
</Custom>
</InstallExecuteSequence>

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