WIX - How to selectively uninstall the <Bundle> - wix

I want to retain the previous versions of my Bootstrapper App, how to achieve this?
I know that we can use the Upgrade tag in MSI where we can identify the different versions and perform uninstall operations base on those.
Now, I have a Bundle Application that has one or more MSI which use some UpgradeCode. Each time I create a new build I just version up the MSI and this Bundle Application. When I proceed with installing of later version of Bundle App, it uninstall the previous Bundle version, which is not what I want. I want to retain the previous versions of my Bundle Application.
Is there anything like UpgradeVersion in Bundle as well, where we would be able to identify the diferent versions and do selectively uninstall.
My Bundle file code snippet :
<Bundle Name="myApp"
Version="1.0.0.0"
Manufacturer="Myself"
UpgradeCode="SOME-GUID">
<BootstrapperApplicationRef Id="ManagedBootstrapperApplicationHost" >
...
</BootstrapperApplicationRef>
<Chain>
<PackageGroupRef Id= 'WindowsInstaller45'/>
<PackageGroupRef Id ='NetFx45Offline'/>
<PackageGroupRef Id ='MY_MSI'/>
</Chain>
</Bundle>
<Fragment Id ='PkgFragments'>
<PackageGroup Id ="MY_MSI">
<MsiPackage SourceFile= "$(var.Installer.TargetPath)"
Id="MYAPP"
Cache ="yes"
Visible ="no"
DisplayInternalUI ="no"
Permanent="no">
<MsiProperty Name='INSTALLLOCATION' Value='[InstallFolder]' />
<MsiProperty Name='SELECT_UNINST' Value='[UninstallPrevVersion]' />
</MsiPackage>
</PackageGroup>
</Fragment>
My Product WIX file code snippet
<Product Id="*"
Name="$(var.ProductName)"
Version="$(var.ProductVersion)"
Manufacturer="$(var.ManufacturerName)"
UpgradeCode="$(var.UpgradeCode)">
<Property Id="SELECT_UNINST" Secure="yes">1</Property>
<Upgrade Id="SOME-GUID2">
<UpgradeVersion Minimum="0.0.0.0" Maximum="$(var.ProductVersion)" IncludeMinimum="yes" IncludeMaximum="yes" Property="UNINSTALL_PREV_VERSION" />
</Upgrade>
<CustomAction Id="UninstPrev" Property="UNINSTALL_PREV_VERSION" Value="0" />
<InstallExecuteSequence>
<Custom Action="UninstPrev" Before="InstallInitialize"><![CDATA[SELECT_UNINST <> 1]]></Custom>
<RemoveExistingProducts Overridable="no" After="UninstPrev"></RemoveExistingProducts>
</InstallExecuteSequence>
</Product>

I'll put this as an answer too.
If you don't want to remove your previous versions don't treat the new version as an upgrade to the old one. This means change the upgrade GUID and change the product GUID. If you need to remove a specific version, add the bundle as a <RelatedBundle> in your Bundle definition and properly handle OnPlanRelatedBundle in your Bootstrapper Application.
<RelatedBundle Action="Detect" Id="$(var.ProductVersion622UpgradeGUID)"/>
Additionally, any msi packages you install also would need to employ the same behaviour of new upgrade GUIDs if you don't want removal between "upgrades". Keep a list of which GUIDs are with which released versions. If you want to remove specific versions in a release of your msi you need to add
<Upgrade Id="$(var.Version6InstallerUpgradeGUID)" >
<UpgradeVersion
IncludeMaximum ="no"
IncludeMinimum="yes"
Maximum="6.0.0.1"
Minimum="6.0.0.0"
MigrateFeatures="no"
Property="V6FOUND"
OnlyDetect="no" />
</Upgrade>
I would consider this requirement very odd and would suggest you really think upon whether or not you really want to support this kind of behaviour.
Also to note, the entry in the ARP for the bootstrapper existing doesn't necessarily mean the products it installed are still on the system. You can test this by always setting pRequestedState = RequestState.Present; in OnPlanRelatedBundle and setting your msi packages to visible="yes". You will have the old bundle listed in the ARP but the packages it installs were probably upgraded by the newer version so it's just an entry that doesn't mean anything.

Related

Cannot perform upgrade and uninstall with WiX installer

I have a simple installer and I want to be able to perform upgrades and do proper uninstalls without having to manually generate a new ID each time.
This is my code (the relevant parts):
<Product Id="*" UpgradeCode="$(var.UpgradeCode)" Name="$(var.ProductName)"
Language="!(loc.Language)" Codepage='1252' Version="$(var.ProductVersion)" Manufacturer="$(var.Manufacturer)">
<Package Id='*' Keywords='Installer' Description="My Installer" Manufacturer='$(var.Manufacturer)'
InstallPrivileges='elevated' InstallScope='perMachine'
InstallerVersion='200' Compressed='yes'/>
<MajorUpgrade Schedule="afterInstallValidate"
DowngradeErrorMessage="A later version of [ProductName] is already installed"
AllowSameVersionUpgrades="yes"
AllowDowngrades="no" />
<InstallUISequence>
<Show Dialog="WelcomeDlg" After="CostFinalize" />
</InstallUISequence>
</Product>
The problem is that I cannot seem to get upgrades and uninstalls to work with the same code/installer.
If I use Product Id="*", I'm able to perform upgrades, but when I try to uninstall, only the entry from Add/Remove Programs is removed. The installed files, however, remain in Program Files.
If I use Product Id="some random guid", I'm able to uninstall, but I'm no longer able to perform upgrades.
So my questions is:
Can I perform upgrades and uninstalls with a wildcard Id (i.e. Product Id="*"), or do I have to manually generate a new ID each time?
Thanks!
I used (Product Id="*") in my WiX installer and it is still able to perform upgrades and uninstalls. My code for Product, Package and Major Upgrade look almost identical to yours so I think the problem lies somewhere else.
Do you have this in your Product section to tell WiX which component groups to install/uninstall? (see code)
<Feature Id="ProductFeature" Title="[ProductName]" Level="1">
<ComponentGroupRef Id="ComponentGroup1" />
<ComponentRef Id="DesktopApplicationShortcut" />
</Feature>
Edit: I have since noticed one other thing that may help you out. I was recently having issues with my program not removing the Desktop Shortcut during Uninstall, despite it working in the past. I have since changed the Guid from "*" to a Guid code and it is now being removed. I think it is the program recognizing the Component.
<Component Id="DesktopApplicationShortcut" Guid="{Create Guid Code}">

Entry for WiX bundle is not removed from the ARP list when uninstalled via UpgradeVersion element

Our application is installed using a WiX bootstrapper. Consequently, the Windows 10 Apps and Features list (a.k.a. ARP) shows an entry for the bundle, and another entry for the .msi which is contained within it.
On my system, I have OurApp v.9.0 installed, as well as v.9.1 Beta. When I install the upgrade, v.9.1 Full Release, it is seen as an upgrade to v.9.0, which is automatically uninstalled. v.9.1 Beta is also uninstalled by use of the following code:
<!-- Uninstall Beta Version [only use this for Full Release] -->
<?if Not $(var.Phase) = "Beta" ?>
<Upgrade Id='233E450E-182F-4823-9C24-2F28A93A52A8'>
<UpgradeVersion OnlyDetect='no' Property='OLDINSTALLER' Minimum='0.0.0' />
</Upgrade>
<?endif?>
Unfortunately, the entry for OurApp 9.1 Beta bundle is sometimes left behind in the ARP list after uninstalling. (The OurApp 9.1 Beta .msi package was successfully removed from the ARP list.) If I try to uninstall the Beta bundle again, it simply disappears without really doing anything. Usually, uninstalling the app from ARP will cause some uninstallation dialogs to appear, but in this case, they don't appear, the entry is simply removed from ARP.
I have looked at the following posts for guidance:
WiX upgrade didn't remove the earlier product from ARP
MSI uninstall does not remove product entry in program features
After using msiexec to uninstall a program it remains in the control panel (add/remove programs)
Unfortunately, these don't seem to be describing quite the same situation as I'm seeing, and I don't understand the suggestions well enough to determine what to do in our case. I did happen to see this comment:
"Duplicate installations are very common in such cases as a by-product of rapid test cycles."
Since "rapid test cycles" would describe well our situation, I'm wondering if this might be the case for us. However, I have 2 difficulties:
I don't understand how to confirm that this is happening or what to do about it.
I get the impression that this would be unlikely to occur on an end-user's system, since they are not participating in these "rapid test cycles". Do we actually need to do anything?
I would appreciate any input / advice on dealing with this situation.
UPDATE:
Here is the WiX code for building our bundle:
<?xml version="1.0"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:bal="http://schemas.microsoft.com/wix/BalExtension"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"
xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension"
xmlns:dep="http://schemas.microsoft.com/wix/DependencyExtension">
<Bundle
Name='UsefulApp $(var.TruncatedVersion) $(var.Phase)'
Version='$(var.VersionNumber)'
UpgradeCode='$(var.UpgradeCode)'
Tag='UsefulFrmwrkBndl'
IconSourceFile='$(var.UsefulInstallIcon)'
Copyright="Copyright ©$(var.CurrentYear), $(var.ProducedBy). All Rights Reserved."
Manufacturer='$(var.ProducedBy)'>
<bal:Condition Message="32-bit Windows is no longer supported."> (VersionNT64 >= v6.0) </bal:Condition>
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.HyperlinkLicense">
<Payload SourceFile="UsefulLicense.htm" />
</BootstrapperApplicationRef>
<!--<RelatedBundle Id='$(var.UpgradeCode)' Action='Detect'/>-->
<WixVariable Id="WixStdbaLicenseUrl" Value="UsefulLicense.htm" />
<WixVariable Id="WixStdbaLogo" Value=".\resources\image_option_1.bmp" />
<WixVariable Id="WixStdbaThemeXml" Value="UsefulHyperlinkTheme.xml" />
<WixVariable Id="WixStdbaThemeWxl" Value="UsefulHyperlinkTheme.wxl" />
<Chain>
<PackageGroupRef Id="NetFx48" />
<PackageGroupRef Id="redist_vc14" />
<RollbackBoundary />
<PackageGroupRef Id='UsefulFrameworkPackGroup'/>
</Chain>
</Bundle>
<Fragment Id='UsefulFrag'>
<PackageGroup Id='UsefulFrameworkPackGroup'>
<MsiPackage Id='UsefulMsiPack'
DisplayName='UsefulApp $(var.VersionNumber)'
DisplayInternalUI='yes'
ForcePerMachine='yes'
InstallCondition='1'
SourceFile='UsefulApp_$(var.VersionNumber)_Installer.msi'
Visible='yes'
Vital='yes'>
</MsiPackage>
</PackageGroup>
<util:RegistrySearch Root="HKLM" Key="SOFTWARE\Microsoft\Net Framework Setup\NDP\v4\Full"
Value="Version" Variable="Netfx48FullVersion" />
<util:RegistrySearch Root="HKLM" Key="SOFTWARE\Microsoft\Net Framework Setup\NDP\v4\Full"
Value="Version" Variable="Netfx48x64FullVersion" Win64="yes" />
</Fragment>
</Wix>

Wix - Upgrade will old installation and install new one

I want that my installer, if detect a old one, previously uninstall it and then launch the installation of the new one.
I've the following Wix XML:
<Product Id="16bf910b-3b0f-4240-914a-81526bce35f4"
Name="MyProduct"
Language="1033"
Version="1.0.0.0"
Manufacturer="MyCompany"
UpgradeCode="6ba28d97-41de-4371-a236-b757b7840f7b">
<Package InstallerVersion="200" Compressed="yes" />
<Upgrade Id="6ba28d97-41de-4371-a236-b757b7840f7b">
<UpgradeVersion Minimum="0.0.0.0"
IncludeMinimum="yes"
OnlyDetect="no"
Maximum="1.0.0.0"
IncludeMaximum="yes"
Property="PREVIOUSFOUND" />
</Upgrade>
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallValidate"/>
</InstallExecuteSequence>
When generating the MSI file, install it (version 1.0.0.0), it's ok.
Now I changed the Product/#Version to 1.0.1.0 and click on MSI again, at this point I get a messge : "A previous installation of this product exists, please remove it first ...".
How can I modify this behavior?
Thanks
Product#Id maps to the Windows Installer ProductCode property. This Id must change from build to build in order to be a Major Upgrade. You can set it to "*" to let the compiler handle this for you.

How to get WiX major upgrade working?

I am struggling to enable the major upgrade functionality in WiX.
I want every new version of the installer to be a major upgrade (full uninstall, then new install) as we don't want different upgrade and clean install versions.
I started off trying to do it using the tag stuff, but I kept getting "Another version is installed." error message when I run the installer.
So I implemented the new tag that was added in V3.5 to make upgrades easier. I was still getting the error message.
I then read somewhere that you need to change the Id GUID for each new version. So I set Id="*" to get WiX to generate them.
Now when I install the newer version it doesn't uninstall the older version, and you end up with two installations to the same folder. I worked this out because running either MSI (new or old) would bring up the repair/remove screen.
Also the program was not overwritten with the new version.
Here is the start of my WiX script:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*"
Name="Foo"
Language="1033"
Codepage="1252"
Version="!(bind.FileVersion.Foo.exe)"
Manufacturer="Foo Bar Ltd."
UpgradeCode="dac2fab2-7d76-4e47-b25f-0748380dab81">
<Package
Description="Foo"
Comments="This installer database contains the logic and data required to install Foo."
InstallerVersion="300"
Languages="1033"
SummaryCodepage="1252"
Platform="x86"
Compressed="yes" />
<!-- Remove older versions -->
<!-- Important note: MSI ignores the last version digit 1.0.0.? when comparing versions, so always change at least the 3rd digit for new external releases-->
<MajorUpgrade DowngradeErrorMessage="The version currently installed is newer than the version you are attempting to install."/>
Here's a snippet of what I use for all my packages, refined over many internal and public releases
<Product Id="*"
UpgradeCode="$(var.Property_UpgradeCode)"
Name="!(loc.ApplicationName)"
Language="!(loc.Property_ProductLanguage)"
Version="$(var.version)"
Manufacturer="!(loc.ManufacturerName)" >
<Package Description="!(loc.Package_Description) $(var.version)"
Comments="!(loc.Package_Comments)"
Manufacturer="!(loc.ManufacturerName)"
InstallerVersion="301"
Compressed="yes"
InstallPrivileges="elevated"
InstallScope="perMachine"
Platform="$(var.ProcessorArchitecture)" />
<Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />
<Upgrade Id="$(var.Property_UpgradeCode)">
<UpgradeVersion OnlyDetect="yes"
Minimum="$(var.version)"
Property="NEWERVERSIONDETECTED"
IncludeMinimum="no" />
<UpgradeVersion OnlyDetect="no"
Maximum="$(var.version)"
Property="OLDERVERSIONBEINGUPGRADED"
IncludeMaximum="no" />
<!-- Detect for changes in 4th field only -->
<UpgradeVersion Property="ANOTHERBUILDINSTALLED"
Maximum="$(var.version)" Minimum="$(var.version)"
IncludeMinimum="yes" IncludeMaximum="yes" OnlyDetect="yes" />
</Upgrade>
<CustomAction Id="CA_BlockOlderVersionInstall" Error="!(loc.LaunchCondition_LaterVersion)" />
<CustomAction Id="CA_BlockAnotherBuildInstall" Error="!(loc.LaunchCondition_AnotherBuild)" />
<InstallExecuteSequence>
<Custom Action="CA_BlockOlderVersionInstall" After="FindRelatedProducts">
<![CDATA[NEWERVERSIONDETECTED]]>
</Custom>
<!-- Prevent installation on 4th version field change only -->
<Custom Action="CA_BlockAnotherBuildInstall" After="FindRelatedProducts">
<![CDATA[ANOTHERBUILDINSTALLED]]>
</Custom>
<LaunchConditions After="AppSearch" />
<!-- Schedule RemoveExistingProducts early -->
<RemoveExistingProducts After="InstallInitialize" />
</InstallExecuteSequence>
<InstallUISequence>
<Custom Action="CA_BlockOlderVersionInstall" After="FindRelatedProducts">
<![CDATA[NEWERVERSIONDETECTED]]>
</Custom>
<!-- Prevent installation on 4th version field change only -->
<Custom Action="CA_BlockAnotherBuildInstall" After="FindRelatedProducts">
<![CDATA[ANOTHERBUILDINSTALLED]]>
</Custom>
<LaunchConditions After="AppSearch" />
</InstallUISequence>
<!-- .... -->
</Product>
If it's of any use to those who discover this thread, I've also encountered a similar problem which I've just figured out.
In my case (and still having been in early stages of developing my installer), the critical difference was that, between versions, I had switched from a per-user install to a per-machine install. More specifically, I'd added the following line to my Product.wxs:
<Property Id='ALLUSERS' Value='1'/>
I'm still getting my head around many of the idiosyncrasies of Windows Installers, but I'd assume that by switching the type of installation in this way would be comparable with shifting to a mutually exclusive stream of versioning in many ways (even enabling two identical versions to be installed in parallel!).
It's a shame that the Windows Control Panel doesn't clearly distinguish between installations which are per-user and all-users.
I know this post is old and answered, but, in case anyone runs across this, I had issues with my upgrade installer. The upgrade sections were all fine. The installer would run, but, the previous version was never removed, therefore, the new version was not installed. The issue was this
<Feature Id="ProductBinaries" Title="ProductBinariesInstaller" Level="0">
The Level="0" above, should have been Level="1" as it is below:
<Feature Id="ProductBinaries" Title="ProductBinariesInstaller" Level="1">
Scott

Wix Major Upgrade, what am I doing wrong?

Upgrades work fine if no components have changed, but any time a component changes the upgrade fails and it requires the user to manually uninstall and reinstall.
Some snippets:
<Product Id="*" Name="My Application" Language="1033" Version="!(bind.FileVersion.ClientEXE)" Manufacturer="My Company" UpgradeCode="MYGUID-b94a-44eb-8e92-9286f1d89bbd">
<Package Id="*" Description="My Installer" Comments="Copyright My Company 2008" InstallerVersion="200" Compressed="yes" />
<Upgrade Id="MYGUID-b94a-44eb-8e92-9286f1d89bbd">
<UpgradeVersion Language="1033" Property="UPGRADEFOUND" Minimum="0.0.0.0" Maximum="99.99.99.99" IncludeMinimum="yes" IncludeMaximum="yes" />
</Upgrade>
<InstallExecuteSequence>
<RemoveExistingProducts Before="InstallInitialize" />
</InstallExecuteSequence>
Also, have some issue with the following registry key sometimes not removing on uninstall and I don't understand why:
<Component Id="InstalledRegistry" Guid="SOMEGUID-0a17-4c6b-983d-8f3feb3a7724">
<RegistryKey Id="InstalledRegKey" Root="HKMU" Key="SOFTWARE\MyCompany\Client" Action="createAndRemoveOnUninstall">
<RegistryValue Name="Version" Type="string" Value="!(bind.FileVersion.ClientEXE)" KeyPath="yes"/>
</RegistryKey>
</Component>
That's what the bootstrapper checks to know whether to launch msiexec with "REINSTALL=ALL REINSTALLMODE=vamus" or not, so if it was uninstalled but the registry key didn't get removed setup would try to do an upgrade and fail silently.
Let me know if any more information is needed
Edit: There was some other issue afterwards with only some files being updated. Changed RemoveExistingProducts to After="InstallValidate" and that resolved that. Makes it a little slower since it fully removes the previous install instead of just upgrading files that changed (which it didn't seem to detect properly for me) but it gets the job done.
FWIW, you don't need any commandline arguments to perform a major upgrade.
The code looks ok to me, so might it be that the Version number is not changed? (keeping in mind that Windows Installer only cares about the three first parts if you are using a 4-part version number)