ADDLOCAL property getting set during a PATCH - windows

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>

Related

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.

Preventing Wix from installing All Features in my Product?

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.

How do I get Wix to automatically uninstall an older build of an installer? [duplicate]

At work we use WiX for building installation packages. We want that installation of product X would result in uninstall of the previous version of that product on that machine.
I've read on several places on the Internet about a major upgrade but couldn't get it to work.
Can anyone please specify the exact steps that I need to take to add uninstall previous version feature to WiX?
Finally I found a solution - I'm posting it here for other people who might have the same problem (all 5 of you):
Change the product ID to *
Under product add The following:
<Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
<Upgrade Id="YOUR_GUID">
<UpgradeVersion
Minimum="1.0.0.0" Maximum="99.0.0.0"
Property="PREVIOUSVERSIONSINSTALLED"
IncludeMinimum="yes" IncludeMaximum="no" />
</Upgrade>
Under InstallExecuteSequence add:
<RemoveExistingProducts Before="InstallInitialize" />
From now on whenever I install the product it removed previous installed versions.
Note: replace upgrade Id with your own GUID
In the newest versions (from the 3.5.1315.0 beta), you can use the MajorUpgrade element instead of using your own.
For example, we use this code to do automatic upgrades. It prevents downgrades, giving a localised error message, and also prevents upgrading an already existing identical version (i.e. only lower versions are upgraded):
<MajorUpgrade
AllowDowngrades="no" DowngradeErrorMessage="!(loc.NewerVersionInstalled)"
AllowSameVersionUpgrades="no"
/>
The following is the sort of syntax I use for major upgrades:
<Product Id="*" UpgradeCode="PUT-GUID-HERE" Version="$(var.ProductVersion)">
<Upgrade Id="PUT-GUID-HERE">
<UpgradeVersion OnlyDetect="yes" Minimum="$(var.ProductVersion)" Property="NEWERVERSIONDETECTED" IncludeMinimum="no" />
<UpgradeVersion OnlyDetect="no" Maximum="$(var.ProductVersion)" Property="OLDERVERSIONBEINGUPGRADED" IncludeMaximum="no" />
</Upgrade>
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallInitialize" />
</InstallExecuteSequence>
As #Brian Gillespie noted there are other places to schedule the RemoveExistingProducts depending on desired optimizations. Note the PUT-GUID-HERE must be identical.
The Upgrade element inside the Product element, combined with proper scheduling of the action will perform the uninstall you're after. Be sure to list the upgrade codes of all the products you want to remove.
<Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
<Upgrade Id="00000000-0000-0000-0000-000000000000">
<UpgradeVersion Minimum="1.0.0.0" Maximum="1.0.5.0" Property="PREVIOUSVERSIONSINSTALLED" IncludeMinimum="yes" IncludeMaximum="no" />
</Upgrade>
Note that, if you're careful with your builds, you can prevent people from accidentally installing an older version of your product over a newer one. That's what the Maximum field is for. When we build installers, we set UpgradeVersion Maximum to the version being built, but IncludeMaximum="no" to prevent this scenario.
You have choices regarding the scheduling of RemoveExistingProducts. I prefer scheduling it after InstallFinalize (rather than after InstallInitialize as others have recommended):
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallFinalize"></RemoveExistingProducts>
</InstallExecuteSequence>
This leaves the previous version of the product installed until after the new files and registry keys are copied. This lets me migrate data from the old version to the new (for example, you've switched storage of user preferences from the registry to an XML file, but you want to be polite and migrate their settings). This migration is done in a deferred custom action just before InstallFinalize.
Another benefit is efficiency: if there are unchanged files, Windows Installer doesn't bother copying them again when you schedule after InstallFinalize. If you schedule after InstallInitialize, the previous version is completely removed first, and then the new version is installed. This results in unnecessary deletion and recopying of files.
For other scheduling options, see the RemoveExistingProducts help topic in MSDN. This week, the link is: http://msdn.microsoft.com/en-us/library/aa371197.aspx
You might be better asking this on the WiX-users mailing list.
WiX is best used with a firm understanding of what Windows Installer is doing. You might consider getting "The Definitive Guide to Windows Installer".
The action that removes an existing product is the RemoveExistingProducts action. Because the consequences of what it does depends on where it's scheduled - namely, whether a failure causes the old product to be reinstalled, and whether unchanged files are copied again - you have to schedule it yourself.
RemoveExistingProducts processes <Upgrade> elements in the current installation, matching the #Id attribute to the UpgradeCode (specified in the <Product> element) of all the installed products on the system. The UpgradeCode defines a family of related products. Any products which have this UpgradeCode, whose versions fall into the range specified, and where the UpgradeVersion/#OnlyDetect attribute is no (or is omitted), will be removed.
The documentation for RemoveExistingProducts mentions setting the UPGRADINGPRODUCTCODE property. It means that the uninstall process for the product being removed receives that property, whose value is the Product/#Id for the product being installed.
If your original installation did not include an UpgradeCode, you will not be able to use this feature.
I used this site to help me understand the basics about WiX Upgrade:
http://wix.tramontana.co.hu/tutorial/upgrades-and-modularization
Afterwards I created a sample Installer, (installed a test file), then created the Upgrade installer (installed 2 sample test files). This will give you a basic understanding of how the mechanism works.
And as Mike said in the book from Apress, "The Definitive Guide to Windows Installer", it will help you out to understand, but it is not written using WiX.
Another site that was pretty helpful was this one:
http://www.wixwiki.com/index.php?title=Main_Page
I read the WiX documentation, downloaded examples, but I still had plenty of problems with upgrades. Minor upgrades don't execute uninstall of the previous products despite of possibility to specify those uninstall. I spent more that a day for investigations and found that WiX 3.5 intoduced a new tag for upgrades. Here is the usage:
<MajorUpgrade Schedule="afterInstallInitialize"
DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit."
AllowDowngrades="no" />
But the main reason of problems was that documentation says to use the "REINSTALL=ALL REINSTALLMODE=vomus" parameters for minor and small upgrades, but it doesn't say that those parameters are FORBIDDEN for major upgrades - they simply stop working. So you shouldn't use them with major upgrades.
I would suggest having a look at Alex Shevchuk's tutorial. He explains "major upgrade" through WiX with a good hands-on example at From MSI to WiX, Part 8 - Major Upgrade.
One important thing I missed from the tutorials for a while (stolen from http://www.tramontana.co.hu/wix/lesson4.php) which resulted in the "Another version of this product is already installed" errors:
*Small updates mean small changes to one or a few files where the change doesn't warrant changing the product version (major.minor.build). You don't have to change the Product GUID, either. Note that you always have to change the Package GUID when you create a new .msi file that is different from the previous ones in any respect. The Installer keeps track of your installed programs and finds them when the user wants to change or remove the installation using these GUIDs. Using the same GUID for different packages will confuse the Installer.
Minor upgrades denote changes where the product version will already change. Modify the Version attribute of the Product tag. The product will remain the same, so you don't need to change the Product GUID but, of course, get a new Package GUID.
Major upgrades denote significant changes like going from one full version to another. Change everything: Version attribute, Product and Package GUIDs.
I'm using the latest version of WiX (3.0) and couldn't get the above working. But this did work:
<Product Id="*" UpgradeCode="PUT-GUID-HERE" ... >
<Upgrade Id="PUT-GUID-HERE">
<UpgradeVersion OnlyDetect="no" Property="PREVIOUSFOUND"
Minimum="1.0.0.0" IncludeMinimum="yes"
Maximum="99.0.0.0" IncludeMaximum="no" />
</Upgrade>
Note that PUT-GUID-HERE should be the same as the GUID that you have defined in the UpgradeCode property of the Product.
Below worked for me.
<Product Id="*" Name="XXXInstaller" Language="1033" Version="1.0.0.0"
Manufacturer="XXXX" UpgradeCode="YOUR_GUID_HERE">
<Package InstallerVersion="xxx" Compressed="yes"/>
<Upgrade Id="YOUR_GUID_HERE">
<UpgradeVersion Property="REMOVINGTHEOLDVERSION" Minimum="1.0.0.0"
RemoveFeatures="ALL" />
</Upgrade>
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallInitialize" />
</InstallExecuteSequence>
Please make sure that the UpgradeCode in Product is matching to Id in Upgrade.
This is what worked for me, even with major DOWN grade:
<Wix ...>
<Product ...>
<Property Id="REINSTALLMODE" Value="amus" />
<MajorUpgrade AllowDowngrades="yes" />

How to implement WiX installer upgrade?

At work we use WiX for building installation packages. We want that installation of product X would result in uninstall of the previous version of that product on that machine.
I've read on several places on the Internet about a major upgrade but couldn't get it to work.
Can anyone please specify the exact steps that I need to take to add uninstall previous version feature to WiX?
Finally I found a solution - I'm posting it here for other people who might have the same problem (all 5 of you):
Change the product ID to *
Under product add The following:
<Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
<Upgrade Id="YOUR_GUID">
<UpgradeVersion
Minimum="1.0.0.0" Maximum="99.0.0.0"
Property="PREVIOUSVERSIONSINSTALLED"
IncludeMinimum="yes" IncludeMaximum="no" />
</Upgrade>
Under InstallExecuteSequence add:
<RemoveExistingProducts Before="InstallInitialize" />
From now on whenever I install the product it removed previous installed versions.
Note: replace upgrade Id with your own GUID
In the newest versions (from the 3.5.1315.0 beta), you can use the MajorUpgrade element instead of using your own.
For example, we use this code to do automatic upgrades. It prevents downgrades, giving a localised error message, and also prevents upgrading an already existing identical version (i.e. only lower versions are upgraded):
<MajorUpgrade
AllowDowngrades="no" DowngradeErrorMessage="!(loc.NewerVersionInstalled)"
AllowSameVersionUpgrades="no"
/>
The following is the sort of syntax I use for major upgrades:
<Product Id="*" UpgradeCode="PUT-GUID-HERE" Version="$(var.ProductVersion)">
<Upgrade Id="PUT-GUID-HERE">
<UpgradeVersion OnlyDetect="yes" Minimum="$(var.ProductVersion)" Property="NEWERVERSIONDETECTED" IncludeMinimum="no" />
<UpgradeVersion OnlyDetect="no" Maximum="$(var.ProductVersion)" Property="OLDERVERSIONBEINGUPGRADED" IncludeMaximum="no" />
</Upgrade>
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallInitialize" />
</InstallExecuteSequence>
As #Brian Gillespie noted there are other places to schedule the RemoveExistingProducts depending on desired optimizations. Note the PUT-GUID-HERE must be identical.
The Upgrade element inside the Product element, combined with proper scheduling of the action will perform the uninstall you're after. Be sure to list the upgrade codes of all the products you want to remove.
<Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
<Upgrade Id="00000000-0000-0000-0000-000000000000">
<UpgradeVersion Minimum="1.0.0.0" Maximum="1.0.5.0" Property="PREVIOUSVERSIONSINSTALLED" IncludeMinimum="yes" IncludeMaximum="no" />
</Upgrade>
Note that, if you're careful with your builds, you can prevent people from accidentally installing an older version of your product over a newer one. That's what the Maximum field is for. When we build installers, we set UpgradeVersion Maximum to the version being built, but IncludeMaximum="no" to prevent this scenario.
You have choices regarding the scheduling of RemoveExistingProducts. I prefer scheduling it after InstallFinalize (rather than after InstallInitialize as others have recommended):
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallFinalize"></RemoveExistingProducts>
</InstallExecuteSequence>
This leaves the previous version of the product installed until after the new files and registry keys are copied. This lets me migrate data from the old version to the new (for example, you've switched storage of user preferences from the registry to an XML file, but you want to be polite and migrate their settings). This migration is done in a deferred custom action just before InstallFinalize.
Another benefit is efficiency: if there are unchanged files, Windows Installer doesn't bother copying them again when you schedule after InstallFinalize. If you schedule after InstallInitialize, the previous version is completely removed first, and then the new version is installed. This results in unnecessary deletion and recopying of files.
For other scheduling options, see the RemoveExistingProducts help topic in MSDN. This week, the link is: http://msdn.microsoft.com/en-us/library/aa371197.aspx
You might be better asking this on the WiX-users mailing list.
WiX is best used with a firm understanding of what Windows Installer is doing. You might consider getting "The Definitive Guide to Windows Installer".
The action that removes an existing product is the RemoveExistingProducts action. Because the consequences of what it does depends on where it's scheduled - namely, whether a failure causes the old product to be reinstalled, and whether unchanged files are copied again - you have to schedule it yourself.
RemoveExistingProducts processes <Upgrade> elements in the current installation, matching the #Id attribute to the UpgradeCode (specified in the <Product> element) of all the installed products on the system. The UpgradeCode defines a family of related products. Any products which have this UpgradeCode, whose versions fall into the range specified, and where the UpgradeVersion/#OnlyDetect attribute is no (or is omitted), will be removed.
The documentation for RemoveExistingProducts mentions setting the UPGRADINGPRODUCTCODE property. It means that the uninstall process for the product being removed receives that property, whose value is the Product/#Id for the product being installed.
If your original installation did not include an UpgradeCode, you will not be able to use this feature.
I used this site to help me understand the basics about WiX Upgrade:
http://wix.tramontana.co.hu/tutorial/upgrades-and-modularization
Afterwards I created a sample Installer, (installed a test file), then created the Upgrade installer (installed 2 sample test files). This will give you a basic understanding of how the mechanism works.
And as Mike said in the book from Apress, "The Definitive Guide to Windows Installer", it will help you out to understand, but it is not written using WiX.
Another site that was pretty helpful was this one:
http://www.wixwiki.com/index.php?title=Main_Page
I read the WiX documentation, downloaded examples, but I still had plenty of problems with upgrades. Minor upgrades don't execute uninstall of the previous products despite of possibility to specify those uninstall. I spent more that a day for investigations and found that WiX 3.5 intoduced a new tag for upgrades. Here is the usage:
<MajorUpgrade Schedule="afterInstallInitialize"
DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit."
AllowDowngrades="no" />
But the main reason of problems was that documentation says to use the "REINSTALL=ALL REINSTALLMODE=vomus" parameters for minor and small upgrades, but it doesn't say that those parameters are FORBIDDEN for major upgrades - they simply stop working. So you shouldn't use them with major upgrades.
I would suggest having a look at Alex Shevchuk's tutorial. He explains "major upgrade" through WiX with a good hands-on example at From MSI to WiX, Part 8 - Major Upgrade.
One important thing I missed from the tutorials for a while (stolen from http://www.tramontana.co.hu/wix/lesson4.php) which resulted in the "Another version of this product is already installed" errors:
*Small updates mean small changes to one or a few files where the change doesn't warrant changing the product version (major.minor.build). You don't have to change the Product GUID, either. Note that you always have to change the Package GUID when you create a new .msi file that is different from the previous ones in any respect. The Installer keeps track of your installed programs and finds them when the user wants to change or remove the installation using these GUIDs. Using the same GUID for different packages will confuse the Installer.
Minor upgrades denote changes where the product version will already change. Modify the Version attribute of the Product tag. The product will remain the same, so you don't need to change the Product GUID but, of course, get a new Package GUID.
Major upgrades denote significant changes like going from one full version to another. Change everything: Version attribute, Product and Package GUIDs.
I'm using the latest version of WiX (3.0) and couldn't get the above working. But this did work:
<Product Id="*" UpgradeCode="PUT-GUID-HERE" ... >
<Upgrade Id="PUT-GUID-HERE">
<UpgradeVersion OnlyDetect="no" Property="PREVIOUSFOUND"
Minimum="1.0.0.0" IncludeMinimum="yes"
Maximum="99.0.0.0" IncludeMaximum="no" />
</Upgrade>
Note that PUT-GUID-HERE should be the same as the GUID that you have defined in the UpgradeCode property of the Product.
Below worked for me.
<Product Id="*" Name="XXXInstaller" Language="1033" Version="1.0.0.0"
Manufacturer="XXXX" UpgradeCode="YOUR_GUID_HERE">
<Package InstallerVersion="xxx" Compressed="yes"/>
<Upgrade Id="YOUR_GUID_HERE">
<UpgradeVersion Property="REMOVINGTHEOLDVERSION" Minimum="1.0.0.0"
RemoveFeatures="ALL" />
</Upgrade>
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallInitialize" />
</InstallExecuteSequence>
Please make sure that the UpgradeCode in Product is matching to Id in Upgrade.
This is what worked for me, even with major DOWN grade:
<Wix ...>
<Product ...>
<Property Id="REINSTALLMODE" Value="amus" />
<MajorUpgrade AllowDowngrades="yes" />

Resources