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}">
Related
I should start by clarifying that I am a complete novice and unfamiliar with Wix, so I am relying on looking at other examples.
I have an installer that is working fine but the filename for the MSI needs to change.
My 'Product' section looks roughly like this:
<Product Id="*" Name="MyShellExtension" Language="1033" Version="1.0.0.0" Manufacturer="ACME Inc" UpgradeCode="???????-????-????-????-??????????">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<Feature Id="ProductFeature" Title="MyShellExtension" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
<CustomActionRef Id="InstallShell"/>
</Product>
I found this posting but it's quite old and refers to a property called 'OutputName' that does not appear to be supported in Wix v3.11 which is what I have. WIX: Howto set the name of the msi output file dynamically
BTW when I installed "The latest version" of Wix I found that it had installed 3.11. I'm guessing it's because I'm running Visual Studio 2019 but if that's not the case and it's both possible and recommended to run more recent versions with VS 2019, please advise on where I might have gone wrong with the installation of Wix.
I found that I could right-click the project in Visual Studio and manually set the name there, which solved my initial problem, but I would like to add the version number of the component I'm installing to the filename.
I'm very new to all of this so it would be really helpful to have an example that I can paste in and modify.
The OutPut name property is in a .wixproj MSBuild file if your using VisualStudio / Votive / MSBuild. If your calling candle and light it's not used. You just pass in the parameter to set the output file name.
Premise
I am using WiX Toolset 3.5.
I have successfully released several patches for my product that use the same UpgradeCode and ProductCode. However, the most recent two patches incorrectly went out with a different UpgradeCode. These patches installed successfully, but my latest patch refuses to install.
Here is my release history since the last MSI release:
Installer (10.0.20935.0) with UpgradeCode A.
Patch (10.0.21069.0) with UpgradeCode A.
Patch (10.0.21188.0) with UpgradeCode A.
Patch (10.0.21334.0) with UpgradeCode A.
Patch (10.0.21671.0) with UpgradeCode A.
Patch (10.1.0.264) with UpgradeCode B.
Patch (10.1.0.21682) with UpgradeCode C.
Patch (10.2.0.0), the latest patch, fails regardless of whether I use UpgradeCode A, B or C.
Below is the error message that appears when I try to install patch 10.2.0.0:
The upgrade patch cannot be installed by the Windows Installer service because the program to be upgraded may be missing, or the upgrade patch may update a different version of the program. Verify that the program to be upgraded exists on your computer and that you have the correct upgrade patch.
The user is not allowed to install the patch.
Question
I need to release a patch that
installs successfully on production (10.1.0.21682).
allows me to continue releasing patches in the future.
How do I achieve this?
What have I tried?
I have tried the following, with no success:
Changing the UpgradeCode to A, i.e. the one from 10.0.21671.0 and earlier.
Changing the UpgradeCode to B, i.e. the one from 10.1.0.264.
Changing the UpgradeCode to C, i.e. the one from 10.1.0.21682.
Changing the ProductCode.
Creating a patch straight from 10.0.21671.0 to 10.2.0.0 (though of course in production it will be run on 10.1.0.21682).
All of the above scenarios result in the same error message (given in the premise). I have also found the following question on StackOverflow:
WIX: When upgrading, what to do when there are 2 different UpgradeCodes?
This led to me adding OnlyDetect="no" to the <UpgradeVersion> element of a new <Upgrade> element in my product's .wxs file:
<Upgrade Id="UpgradeCode C">
<UpgradeVersion Property="OLD_PRODUCT_FOUND"
IncludeMaximum="yes"
Maximum="10.2.0.0"
MigrateFeatures="yes"
OnlyDetect="no" />
</Upgrade>
However, this had the exact same outcome as before.
Sample Code
I have created a small project that I use to replicate my scenario.
Below is the .wxs file for version 10.2.0.0 of the product from my test project:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="{8CB0CC73-82B1-495E-B768-D1C38372678A}"
Name="Sample Application"
Language="1033"
Version="10.2.0.0"
Manufacturer="Sample Corporation"
UpgradeCode="{7E72848F-FC99-4737-87DE-91C738B7C5EE}">
<Package Description="Installs a file that will be patched."
Comments="This Product does not install any executables"
InstallerVersion="200"
Compressed="yes" />
<Media Id="1" Cabinet="product.cab" EmbedCab="yes" />
<FeatureRef Id="SampleProductFeature"/>
</Product>
<Fragment>
<Feature Id="SampleProductFeature" Title="Sample Product Feature" Level="1">
<ComponentRef Id="Sample.txt" />
</Feature>
</Fragment>
<Fragment>
<DirectoryRef Id="SampleProductFolder">
<Component Id="Sample.txt" Guid="{d738b2a9-0dbc-4381-9efd-5801723b1569}" DiskId="1">
<File Id="Sample.txt" Name="Sample.txt" Source=".\$(var.Version)\Sample.txt" />
</Component>
</DirectoryRef>
</Fragment>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder" Name="PFiles">
<Directory Id="SampleProductFolder" Name="Patch Sample Directory">
</Directory>
</Directory>
</Directory>
</Fragment>
</Wix>
Below is the .wxs file for the patch to version 10.2.0.0:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Patch
AllowRemoval="no"
Manufacturer="Sample Corp"
MoreInfoURL="http://www.dynamocorp.com/"
DisplayName="Sample Patch"
Description="Small Update Patch"
Classification="Update"
OptimizedInstallMode="yes">
<Media Id="8000" Cabinet="RTM.cab" CompressionLevel="none">
<PatchBaseline Id="RTM">
</PatchBaseline>
</Media>
<PatchFamilyRef Id="SamplePatchFamily"/>
</Patch>
<Fragment>
<PatchFamily Id='SamplePatchFamily' Version='10.2.0.0' Supersede='no'>
</PatchFamily>
</Fragment>
</Wix>
You definitely shouldn't change the ProductCode. If you have been building MSI files that changed the UpgradeCode then maybe more critical items are changing. You built a patch that targets a product with a specific ProductCode and PackageCode (based on the MSI files you created) and that's what it wants.
Most importantly, I'd check that patch 7 with UpgradeCode C did not change the installed product's ProductCode or PackageCode because that's the patch that produced the problem, and if your new patch 8 cannot find a product to patch it's the ProductCode and PackageCode it'll be looking for. That's what the error is saying - the ProductCode (or PackageCode) targeted by this patch is not installed. In other words I doubt very much that the UpgradeCode matters in that error message, and that linked article about upgrading more than one product with a major upgrade has no bearing on a patching issue like this unless you are worried about major upgrades, in which case you just list all the UpgradeCodes that need upgrading, and so it's not an issue.
The solution, it turns out, is as simple as disabling validation of the UpgradeCode for the newest patch. This can be done by setting the UpgradeCode attribute on the Validate to "no".
<Media Id="8000" Cabinet="RTM.cab" CompressionLevel="none">
<PatchBaseline Id="RTM">
<Validate UpgradeCode="no" />
</PatchBaseline>
</Media>
This 10.2.0.0 patch, which introduces a new UpgradeCode, runs successfully on top of 10.1.0.21682, and I was able to successfully execute three subsequent patches. (These patches have UpgradeCode validation enabled and share the same UpgradeCode as 10.2.0.0.)
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.
I wrote an install program with Wix and it worked fine to install my program.
Now I need to update it, so I bumped up the version number but when I go to install the new program over the old one it complains that an older version is already installed and tells me to uninstall it first.
How do I get it to update or automatically uninstall it before reinstalling?
I feel that none of the provided answers are complete or self-contained, so after digging my way through this swamp, here's the steps I think are necessary to get the (utterly self-evident) requirement of an update to work:
Make sure your Product Id changes every time you build. If you don't, you'll always get the "already installed" message the OP mentioned.
<Product Id="*" ...>
Change the Product Version every time the product itself changes. I suppose the best option is to bind it to an assembly version (which should be auto-incremented as well), but of course you could also just change it manually. This step is not strictly required if you use the AllowSameVersionUpgrades attribute in point 4, but I'd venture to say that keeping your product version constant is bad practise in any case.
<Product Version="!(bind.FileVersion.MyAssemblyDll)" ...>
<File Id="MyAssemblyDll" Name="$(var.001_Application.MyAssembly.TargetFileName)" Source="$(var.001_Application.MyAssembly.TargetPath)" />
Keep your UpgradeCode constant (e.g.):
<Product UpgradeCode="f4d7f199-28f6-45d5-ad99-7c62938274be" ...>
Add the MajorUpgrade element (from Wix 3.5.1315.0). To circumnavigate the catch that the MajorUpgrade will disregard changes in the revision number of the product version, add the AllowSameVersionUpgrades (or if you prefer AllowDowngrades) attribute. This way, you will be able to upgrade from e.g. 1.0.0.7 to 1.0.0.8. and not just from 1.0.7.0 to 1.0.8.0. If you don't do this, you may see multiple installations in Programs and Features.
<MajorUpgrade AllowSameVersionUpgrades="yes" DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
Here's my whole .wix file (relevant parts, the two fragments that lead to the assembly which is used for product binding are mostly optional and for illustration, any way you can get a hold of the assembly will work):
<?xml version="1.0" encoding="UTF-8"?>
<?define ProductVersion="!(bind.FileVersion.MyAssemblyDll)"?>
<?define UpgradeCode="f4d7f199-28f6-45d5-ad99-7c62938274be"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension">
<Product
Id="*"
Name="My Product's name"
Language="1033"
Version="$(var.ProductVersion)"
Manufacturer="My company"
UpgradeCode="$(var.UpgradeCode)"
Codepage="1252">
<Package
InstallerVersion="200"
Compressed="yes"
InstallScope="perUser"
Description="My product description"
Manufacturer="My company"
Languages="1033"
SummaryCodepage="1252"
InstallPrivileges="limited" />
<MajorUpgrade AllowSameVersionUpgrades="yes"
DowngradeErrorMessage="A newer version of [ProductName] is already installed. If you are sure you want to downgrade, remove the existing installation via Programs and Features." />
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="LocalAppDataFolder">
<Directory Id="INSTALLFOLDER" Name="My Install Dir" >
<Component Id="INSTALLFOLDER" Guid="f6ba8a12-6493-4911-8edd-dce90e1d8e8b" >
<RemoveFolder On="both" Id="INSTALLFOLDER"/>
<RegistryValue Root="HKCU" Key="Software\[Manufacturer]\[ProductName]" Type="string" Value="My Registry value" />
</Component>
</Directory>
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" >
<Component Id="ProductComponent" Guid="1939f0f5-19f6-498b-bf95-8f1c81501294" DiskId="1" Directory="INSTALLFOLDER" >
<File Id="MyAssemblyDll" Name="$(var.001_MyApplication.MyAssembly.TargetFileName)" Source="$(var.001_MyApplication.MyAssembly.TargetPath)" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>
I checked through all the posts mentioned above and still spent ages trying to get this to work.
The hint on the official HOWTO for upgrades in Step 3 helped a lot: You need a new Product/#Id to disable the message "Another version of this product is already installed".
I used this upgrade section (child of Product):
<Upgrade Id="$(var.UpgradeCode)">
<UpgradeVersion Minimum="1.0.0"
IncludeMinimum="yes"
OnlyDetect="no"
Maximum="$(var.Version)"
IncludeMaximum="no"
Property="PREVIOUSFOUND" />
</Upgrade>
Note that OnlyDetect is set to "no". This triggers the removal of the old version, if you have the following section (child of Product):
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallInitialize"/>
</InstallExecuteSequence>
Also note that apparently, only the first three components of the version number are used to check for upgrades...
You need to use the upgrade table:
<Upgrade Id='15E2DAFB-35C5-4043-974B-0E342C25D76A'>
<UpgradeVersion Property='OLDVERSIONFOUND' IncludeMinimum='no' Minimum='0.0.0.0' />
</Upgrade>
You need also add an action:
<InstallExecuteSequence>
<LaunchConditions After='AppSearch' />
<RemoveExistingProducts After='InstallValidate' />
</InstallExecuteSequence>
Here is a tutorial
I tried this and it worked for me.
Put your product tag like this:
Product Id="*" Name="Something" Language="1033" Version="1.0.0.0" Manufacturer="Someone" UpgradeCode="43ab28d7-6681-4a05-a6b5-f980733aeeed"
Product Id should be set to * so that every time you build your project, it takes different id.
Nest a MajorUpgrade tag inside your Package element which looks like:
MajorUpgrade AllowDowngrades="no" DowngradeErrorMessage="A newer version of [ProductName] is already installed." AllowSameVersionUpgrades="yes" /
So, every time you update your version(or your version is same, not less than current version), it reinstalls your product by removing the previous files and installing the product files.
It will not downgrade your product.
Just put this element under the Product element:
<MajorUpgrade AllowDowngrades="yes" />
More info in this HowTo
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)