When using Visual Studio Setup project, if an installation fails, it will revert back to the previous version of the installation, so it restored the previous files.
But, when using WiX installer, if the installation fails, WiX installer removed all the files on the installed folder.
How can I make WiX installer restore the previous files when the installation fails ?
Thank you.
This is in Product.wxs of a Wix installer for a Windows Service:
<Product Id="*" Name="WixWindowsService2012" Language="1033" Version="1.0.0.1" Manufacturer="aaa" UpgradeCode="blabla">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" Platforms="x64"/>
<Upgrade Id="blabla">
<UpgradeVersion OnlyDetect="no" Property="PREVIOUSFOUND"
Minimum="1.0.0.0" IncludeMinimum="yes"
Maximum="99.0.0.0" IncludeMaximum="no" />
</Upgrade>
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<Feature Id="ProductFeature" Title="WixWindowsService2012" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
:
<Component Id="ProductComponent" Win64="yes">
<File Id="WixWindowsService2012.exe" Name="WixWindowsService2012.exe" Source="$(var.WixWindowsService2012.TargetPath)" Vital="yes" KeyPath="yes" DiskId="1"/>
<ServiceInstall
Id="ServiceInstaller"
Type="ownProcess"
Vital="yes"
Name="WixWindowsService2012"
DisplayName="WixWindowsService2012"
Description="A test for WiX installation for Windows Service"
Start="auto"
Account="LocalSystem"
ErrorControl="ignore"
Interactive="no"></ServiceInstall>
<ServiceControl Id="StartService" Start="install" Stop="both" Remove="uninstall" Name="WixWindowsService2012" Wait="yes" />
</Component>
If you had a setup that restored previous versions of the files then by definition it was an upgrade (RemovePreviousVersions in Visual Studio). In WiX you specify an upgrade by using the MajorUpgrade element, so whatever you have in yours isn't sufficient or isn't working. Your UpgradeCode in the WiX project needs to be the same as your previous setup, whether it's WiX or VS. The ProductVersion must be incremented in the first 3 digits, and the ProductCode must be different. In addition, a per-machine install will not upgrade a per user install, just in case that's happening. Creating a verbose log of the install will supply the reason why your upgrade isn't working.
Related
I am using the Wix Toolset to generate an .msi for my application. Everything works when I upgrade to a new version, except every time I run a newer version installation the setup doesn't detect already installed features and instead defaults to the features that are 'required' which means if the user installed any of the other features they are removed unless the user explicitly checks them for installation again.
Is there anyway to have the .msi detect which features are currently installed each time a newer version is installed?
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Product Id="*" UpgradeCode="9e578e3d-0119-425c-8633-f54ffaaa4929" Name="#product.name#" Version="#product.version#" Manufacturer="#product.company#" Language="1033">
<Package InstallerVersion="400" Compressed="yes" InstallScope="perMachine" Comments="#product.version#" Description="#product.description#"/>
<Media Id="1" Cabinet="myapp.cab" EmbedCab="yes" />
<!-- Installer Properties -->
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR" />
<PropertyRef Id="WIX_IS_NETFRAMEWORK_46_OR_LATER_INSTALLED"/>
<!-- Check Existing Install -->
<Upgrade Id="9e578e3d-0119-425c-8633-f54ffaaa4929">
<UpgradeVersion Minimum="#product.version#" OnlyDetect="yes" Property="NEWERVERSIONDETECTED"/>
<UpgradeVersion Minimum="0.0.0" Maximum="#product.version#" IncludeMinimum="yes" IncludeMaximum="no" Property="OLDERVERSIONBEINGUPGRADED"/>
</Upgrade>
<Condition Message="A newer version of this software is already installed.">NOT NEWERVERSIONDETECTED</Condition>
<!-- Prerequisites -->
<Condition Message="This application requires .NET Framework 4.6 or newer. Please install the .NET Framework then run this installer again.">
<![CDATA[Installed OR WIX_IS_NETFRAMEWORK_46_OR_LATER_INSTALLED]]>
</Condition>
<Condition Message="This application is only supported on Windows 7, Windows Server 2008 R2 or higher.">
<![CDATA[Installed OR (VersionNT >= 601)]]>
</Condition>
...
<Feature Id="Feature_Application"
Title="Application"
ConfigurableDirectory="APPLICATIONDIR"
Level="1"
AllowAdvertise="no">
#product.applicationcomponents#
<ComponentRef Id="ApplicationShortcut" />
<ComponentRef Id="CleanupApplicationData" />
</Feature>
<!-- Feature: My Service -->
<Feature Id="Feature_Service"
Title="My Service"
Description="My Service"
ConfigurableDirectory="REPORTDIR"
Level="3"
AllowAdvertise="no">
#product.servicecomponents#
<ComponentRef Id="ServiceShortcut" />
<Component Id="MyServiceInstaller_ServiceControl" Guid="B72CAA3F-F2DB-48D2-90DD-061209AB2CE5" Directory="REPORTDIR">
<CreateFolder />
<File Id="MyService.exe" Name="MyService.exe" KeyPath="yes" Source="#product.sourcedir#\MyService\MyService.exe"/>
<ServiceInstall Id="MyServiceInstaller_ServiceInstall"
Type="ownProcess"
Vital="yes"
Name="Windows Service"
DisplayName="Windows Service"
Description="Windows service"
Start="auto"
Account="NT AUTHORITY\LocalService"
ErrorControl="ignore"
Interactive="no" />
<ServiceControl Id="MyServiceInstaller_ServiceInstall"
Name="My Service"
Stop="both"
Remove="uninstall"
Wait="yes" />
</Component>
</Feature>
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallValidate"/>
</InstallExecuteSequence>
<UIRef Id="WixUI_FeatureTree" />
<UI>
<DialogRef Id="FilesInUse" />
<DialogRef Id="MsiRMFilesInUse" />
<!-- Add the GUI logic for installation -->
</UI>
</Product>
#dpb's answer would solve the problem, because the MajorUpgrade tag has a MigrateFeatures attribute with an implicit default value of yes.
However, it is only relevant if you actually want to create a major update to your product, which has implications. - This is not an option for me.
If you do not want to perform a major update, you must add the MigrateFeatures attribute to the UpgradeVersion tag and explicitly set it's value to yes.
The MigrateFeatureStates action below the InstallExecuteSequence tag is of minor importance only.
This action will not be executed if there is no MigrateFeatures="yes" attribute (implicit or explicit), as described above.
If there is a MigrateFeatures="yes" attribute, the MigrateFeatureStates action will automatically be added to the InstallExecuteSequence table of the installer.
You only need to explicitly define the MigrateFeatureStates action in the InstallExecuteSequence tag, if you want to adjust the action's position in the execution sequence.
Try using MajorUpgrade tag.
`<MajorUpgrade DowngradeErrorMessage="Can’t downgrade." />`
https://stackoverflow.com/a/11028847/7165196
We use the wix 3.9 to create an msi for our product. Our Target: We want to deliver a config file (.txt-file) via the msi. When an config file already exists in the installation folder, the file should not be overwritten by an upgrade. Unfortunately, on an upgrade, Wix removes the configuration file.
The Product Element:
<Product Id="*" Name="$(var.AppName) V$(var.Version) $(var.TargetBuild)" Language="1033" Version="$(var.Version)" Manufacturer="$(var.Manufacturer)" UpgradeCode="$(var.UpgradeCode)">
The $(var.UpgradeCode) is static and will never be changed.
The Upgrade Tags:
<MajorUpgrade DowngradeErrorMessage="A newer version of $(var.AppName) is already installed." AllowSameVersionUpgrades="yes" />
<Upgrade Id="$(var.UpgradeCode)">
<UpgradeVersion Minimum="1.0.0"
IncludeMinimum="yes"
OnlyDetect="yes"
Maximum="$(var.Version)"
IncludeMaximum="yes"
Property="PREVIOUSVERSIONSINSTALLED" />
</Upgrade>
<Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
Here is the config file:
<Component Id="ConfigComponent" NeverOverwrite="yes" Guid="GUID-HERE">
<File Id="ConfigOutput" KeyPath="yes" Name="MyConfig.config" Source="MyConfig.config.bak"/>
</Component>
In Addition, I use RemoveFolderEx to remove generated files by the Application itself. But when I commented out this block, the problem still occurs. But I want to show the codeblock for the completeness:
<Component Id="RemoveAll" Guid="MYGUID">
<RemoveFile Id="RemoveAllFilesOnUninstall" Directory="APPLICATIONFOLDER" Name="*.*" On="uninstall" />
<RemoveFolder Id="RemoveAllFoldersOnUninstall" Directory="APPLICATIONFOLDER" On="uninstall" />
<RegistryValue Root="HKLM" Key="SOFTWARE\$(var.Manufacturer)\$(var.AppName)" Name="Path" Type="string" Value="[APPLICATIONFOLDER]" KeyPath="yes" />
<util:RemoveFolderEx On="uninstall" Property="APPLICATIONFOLDER" />
</Component>
Repro: At first, we install the Software and the file 'MyConfig.config' appears in the application folder as expected. After that, we make changes inside of this config file. At next, we build a second .msi and execute it. When the update is made, all files are overwritten as expected. But we are missing the file 'MyConfig.config' in the installation folder now.
UPDATE:
The attribute Permanent="yes" does also not work as expected. The config File is still removed on an upgrade:
<Component Id="ConfigComponent" Permanent="yes" NeverOverwrite="yes" Guid="GUID-HERE">
<File Id="ConfigOutput" KeyPath="yes" Name="MyConfig.config" Source="MyConfig.config.bak"/>
</Component>
What's happening during your Major Upgrade:
The CostInitialize/CostFinalize actions determine what components in the new MSI should install. The ConfigComponent decides 'not' to install because it's marked as NeverOverwrite="yes".
The old MSI is removed during the RemoveExistingProducts action. The previous config file is removed.
The new MSI is installed. The ConfigComponent does not get installed based on the check from step 1.
A quick solution (although I'm sure there are better approaches out there):
Going forward, mark your ConfigComponent with Permanent="yes" so that MSI never removes it. You'll need to add a custom action that removes the file, and condition it on "$ConfigComponent=2 And Not UPGRADINGPRODUCTCODE" so that it only executes when the component is set to be deleted through a modify or full-uninstall, but not an upgrade.
If your MSI is already shipped to the world and you need to fix the upgrade scenario you'll need to write a custom action that copies the config file to a backup location before the old MSI removes it. Then another custom action to copy the config file back into the correct directory.
I have an application that needs 1. to create DLL files in a Program Files subfolder (e.g. C:\Program Files (x86)\myapp), and 2. to create a registry entry in HKCU. When I run the Remove, I need this subfolder and its files to be deleted, as well as the registry entry.
When I run the installation file of a newer version, I need the new DLL files to replace the existing ones.
I've been struggling getting it to work, having tried several tips from various threads and sites.
So far I get the Program Files to be removed but not the Registry. And I cannot get the file upgrade to work (I change the UpgradeCode & ProductVersion for each new release)
Here is an extract of what I have
<Product Id="$(var.ProductID)"
Name="myapp"
Language="1033"
Version="$(var.ProductVersion)"
UpgradeCode="$(var.UpgradeCode)"
Manufacturer="$(var.Manufacturer)">
<Package Description="Windows installer for myApp $(var.ProductVersion)"
Comments="Execute to install myApp $(var.ProductVersion)"
InstallerVersion="200"
Compressed="yes" />
<Media Id="1" Cabinet="contents.cab" EmbedCab="yes" CompressionLevel="high"/>
<Upgrade Id="$(var.UpgradeCode)">
<UpgradeVersion Minimum="$(var.ProductVersion)"
OnlyDetect="yes"
Property="NEWERVERSIONDETECTED" />
<UpgradeVersion Minimum="1.0.0.0"
IncludeMinimum="yes"
Maximum="$(var.ProductVersion)"
IncludeMaximum="no"
Property="OLDERVERSIONBEINGUPGRADED" />
</Upgrade>
<CustomAction Id="UIandAdvertised" Error="Something about the UI."/>
<Directory Id="TARGETDIR" Name="SourceDir"/>
<Feature Id="Complete"
Title="myApp"
Description="Installation of myApp $(var.ProductVersion)"
Level="1">
<ComponentRef Id="myAppFiles"/>
<ComponentRef Id="RegistryEntry"/>
</Feature>
<Property Id="WIXUI_INSTALLDIR">INSTALLDIR</Property>
<UIRef Id="WixUI_InstallDir"/>
<InstallExecuteSequence>
<RemoveExistingProducts Before="InstallInitialize" />
<RemoveRegistryValues />
</InstallExecuteSequence>
</Product>
My files and reg infos are maintained in a separate file:
<Fragment>
<DirectoryRef Id="TARGETDIR">
<Directory Id="ProgramFilesFolder" Name="PFiles">
<Directory Id="INSTALLDIR" Name="myapp">
<Component Id="myAppFiles" Guid="{xxxx-xxxx-xxxx-xxxx-xxxxxxxx}">
<File Id="myapp.dll" Name="myapp.dll" KeyPath="yes" Source="..\src\bin\x86\Release\myapp.dll" />
</Component>
<Component Id="RegistryEntry" Guid="{xxxxxxx-xxxx-xxxx-xxxx-xxxxxxx}" Win64="no" >
<RegistryKey Root="HKCU" Key="Software\myapp" Action="createAndRemoveOnUninstall">
<RegistryValue Type="string" Value="myapp" />
</RegistryKey>
</Component>
</Directory>
</Directory>
</DirectoryRef>
Any help will be highly appreciated.
Use Product ID ="*",
It changes product id guid for each build.
But keep upgrade code same for product, unless you dont want to support upgrade.
You can use major upgrade tag instead of Upgrade tag. It is easier to use.
<MajorUpgrade AllowDowngrades="no"
AllowSameVersionUpgrades="no"
Schedule="afterInstallValidate"
DowngradeErrorMessage="Newer version of [ProductName] is already installed."/>
Hi I've seen other questions on this topic, but nothing I try seems to work.
On uninstall of my product I get many messages in my log file like this:
Disallowing uninstallation of component: {895A2232-90E3-417B-AF3D-A4F5A8D1C225} since another client exists
This post...
Wix does not remove service and files on uninstall
... prompted me to run MsiInv, which logged this a few times: 'Component x has no parent product'
This post: http://www.itninja.com/question/disallowing-uninstallation-of-component-xxx prompted me to find and delete the orphan entries... I've even tried running AVG registry cleaner.
However the files are still not removed on an uninstall. So I've been testing the solutions above (e.g. removing orphan registry entries) by uninstalling, then manually removing the files, then updating the product version and reinstalling.
Relevant code snippets:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*"
Name="My Product Name"
Language="1033"
Version="1.0.118.0"
Manufacturer="My Company Name"
UpgradeCode="DEA53C73-EE29-4D5E-A3FF-0A09D0F50AF3">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<!--<UIRef Id="WixUI_Minimal" />-->
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<!-- Force administrator-->
<Property Id="MSIUSEREALADMINDETECTION" Value="1" />
<Feature Id="ProductFeature" Title="My Installer Name" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
...
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="CMP_INSTALL_FOLDER" Guid="DA711C12-A960-421F-A6A9-5ECF0DEEE2BC" Permanent ="no">
<RemoveFolder Id='RemovInstallFolder' Directory='INSTALLFOLDER' On='uninstall' />
<RegistryValue Root='HKCU' Key='Software\[Manufacturer]\[ProductName]\InstallFolder' Type='string' Value='' KeyPath='yes' />
</Component>
<Component Id="exampleComponent"
Guid="A0AFBE29-6962-4491-9D2F-D08E0B31C6BA" Permanent ="no">
<File Id="exampleComponentName"
Source="exampleSource"
KeyPath="yes" />
</Component>
</ComponentGroup>
Thanks to Chris for suggesting testing on a fresh image. That led me to the answer.
My problem was that a custom action (which was running an executable) was failing. Once I put a condition of 'NOT installed' to prevent that custom action running on uninstall it started to work
<InstallExecuteSequence>
<Custom Action="CA_RunRegisterDLLScript" After="InstallFiles" >
NOT Installed
</Custom>
</InstallExecuteSequence>
It still doesn't work on the dev machine - I'm giving up on that...
One other tip that I learned along the way was how to find root cause problems in a verbose MSI log file. Short answer - Look for "return value = 3" - the problem's almost always just above it
I found this tip here: http://blogs.msdn.com/b/astebner/archive/2005/08/01/446328.aspx
I have wix bootstapper which includes 4 components: tree exe packages and one msi package. I want to do major update of msi package using bootstrapper below (only main code):
<Bundle Name="$(var.Name)" Version="$(var.Version)" Manufacturer="$(var.Manufacture)" UpgradeCode="$(var.UpgradCode)" Copyright="$(var.Copyright)">
....
<Chain>
<!-- TODO: Define the list of chained packages. -->
<PackageGroupRef Id="NetFx4Full"/>
<PackageGroupRef Id="PostgreSQL"/>
<PackageGroupRef Id="AdobeReader"/>
<PackageGroupRef Id="Application"/>
</Chain>
....
<PackageGroup Id="Application">
<MsiPackage Id="MyApplication"
SourceFile=".\MSI_File\application.msi"
DisplayInternalUI="yes"
Permanent="no"
Vital="yes"
Visible="no"/>
others packages...
</PackageGroup>
and msi code:
<Product Id="*"
Name="$(var.Name)"
Language="$(var.InstallerLanguage)"
Version="$(var.Version)"
UpgradeCode="$(var.UpgradeCode)"
Manufacturer="$(var.Manufacture)">
<Package Description="$(var.PackageDescritpion)"
InstallerVersion="200"
Compressed="yes"
InstallScope="perMachine"
InstallPrivileges="elevated"
Platform="x64"/>
<Media Id="1" Cabinet="contents.cab" EmbedCab="yes" CompressionLevel="high"/>
<Directory Id="TARGETDIR" Name="SourceDir">
</Directory>
<Feature Id="Complete"
Level="1"
ConfigurableDirectory="INSTALLDIR">
<ComponentRef Id="Licence"/>
<ComponentRef Id="StartMenuFoldersComponent"/>
<ComponentRef Id="DatabaseConfigFolder"/>
<ComponentGroupRef Id="BinaryFileGroup"/>
<ComponentGroupRef Id="DatabaseConfigFileGroup"/>
<ComponentRef Id="ApplicationConfigFolder"/>
<ComponentRef Id="RemoveFolderOnUninstall"/>
</Feature>
<!-- Custom actions-->
.....
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallValidate"/>
<!--Other custom actions-->
......
</InstallExecuteSequence>
To build my update msi and bootstrapp I set greater (the same for msi and bootstrapp) product version, for example old version has 1.0.0.0 and newer has 1.0.1.0. Upgrade code as a WIX documentation says remains unchanged. After run my update installer the new version of msi is not installig, in install directory still are old files. Does anyone know what I do wrong?
#Edit
Also I tried by adding MajorUpgrade element but after that bootstrapper doesn't start MSI:
<Media Id="1" Cabinet="contents.cab" EmbedCab="yes" CompressionLevel="high"/>
<MajorUpgrade Schedule="afterInstallInitialize" DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit."/>
<Directory Id="TARGETDIR" Name="SourceDir"/>
#Edit
Bootstrapper logs: http://wklej.to/Msczq
You need to add upgrade information to the .msi package. See http://wixtoolset.org/documentation/manual/v3/howtos/updates/major_upgrade.html for use of the MajorUpgrade element.