I've got two different products (A, B) that install via custom wix installers. For some reason when A is installed and I try to install B, A is uninstalled as part of B installation and vice versa when B is installed, A uninstalls B.
I have very similar WIX files but each one has a different Product UpgradeCode. I've done a bit of searching and it seems everyone has the opposite problem where the upgrade is not uninstalling their product.
Any ideas about what else has to be changed would be much appreciated as I've been banging my head against the wall for hours.
This is one of my wix files. The main difference between this and the other is different cookiecutter variables (guid and formal_name) and "<-- CONTENT -->, <-- CONTENTREFS -->" contents section. Both applications do install to different locations.
<?xml version="1.0"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product
Id="*"
UpgradeCode="{{ cookiecutter.guid }}"
Name="{{ cookiecutter.formal_name }}"
Version="0.1.1"
Manufacturer="{{ cookiecutter.organization_name }}"
Language="1033">
<Package
InstallerVersion="200"
Compressed="yes"
Comments="Windows Installer Package"
/>
<Media Id="1" Cabinet="product.cab" EmbedCab="yes"/>
<Property Id="ARPHELPLINK" Value="https://www.myhome.com" />
<Property Id="ARPURLINFOABOUT" Value="Home Page" />
<Property Id="ARPNOREPAIR" Value="1" />
<Property Id="ARPNOMODIFY" Value="1" />
<MajorUpgrade AllowDowngrades="yes"
AllowSameVersionUpgrades="no"
IgnoreRemoveFailure="no"
Schedule="afterInstallInitialize" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="AppDir" Name="{{ cookiecutter.formal_name }}">
<!-- CONTENT -->
</Directory>
</Directory>
<Directory Id="ProgramMenuFolder">
<Directory Id="ApplicationProgramsFolder" Name="{{ cookiecutter.formal_name }}"/>
<Directory Id="DesktopFolder" Name="{{ cookiecutter.formal_name }}DesktopFolder"/>
</Directory>
</Directory>
<DirectoryRef Id="ApplicationProgramsFolder">
<Component Id="ApplicationShortcutStartMenu" Guid="*">
<Shortcut Id="ApplicationShortcut1" Name="{{ cookiecutter.formal_name }}" Description="{{ cookiecutter.description }}" Target="[DIR_python]\python.exe" WorkingDirectory="AppDir" Arguments="app\start.py" />
<RegistryValue Root="HKCU" Key="Software\{{ cookiecutter.organization_name }}\{{ cookiecutter.formal_name }}" Name="installed" Type="integer" Value="1" KeyPath="yes" />
<RemoveFolder Id="CleanUpShortCut1" Directory="ApplicationProgramsFolder" On="uninstall"/>
</Component>
</DirectoryRef>
<DirectoryRef Id="DesktopFolder">
<Component Id="ApplicationShortcutDesktop" Guid="*">
<Shortcut Id="ApplicationShortcut2" Name="{{ cookiecutter.formal_name }}" Description="{{ cookiecutter.description }}" Target="[DIR_python]\python.exe" WorkingDirectory="AppDir" Arguments="app\start.py" />
<RegistryValue Root="HKCU" Key="Software\{{ cookiecutter.organization_name }}\{{ cookiecutter.formal_name }}DesktopFolder" Name="installed" Type="integer" Value="1" KeyPath="yes" />
<RemoveFolder Id="CleanUpShortCut2" Directory="DesktopFolder" On="uninstall"/>
</Component>
</DirectoryRef>
<Feature Id="DefaultFeature" Level="1">
<!-- CONTENTREFS -->
<ComponentRef Id="ApplicationShortcutStartMenu"/>
<ComponentRef Id="ApplicationShortcutDesktop"/>
</Feature>
<Property Id="ALLUSERS" Value="1"></Property>
</Product>
Upgrade Code: This behavior is consistent with identical upgrade code, please verify if this is the case by using one of the approach shown here to list all upgrade codes for installed setups: How can I find the Upgrade Code for an installed MSI file?
MSI File Hard Facts: Alternatively - or preferably - check the Upgrade table of the actual MSI files involved whether they are installed or not.
Custom Action: I suppose it is also possible that there is a custom action in your installer which uninstalls the other product as a custom action step inserted somewhere in the installation sequences (only a few locations will work). Please inspect your MSI using Orca or some other MSI tool to determine what is in the tables: Custom Action and Upgrade. Please report any suspects.
Launcher: The MSI in question is not launched from a setup.exe is it? Or from a batch file or some automated system for deployment?
Update: Maybe have a look at this answer from yesterday. At least somewhat related: How to avoid having two versions of a product installed with Windows Installer / MSI?
Related
my idea is make an uninstall file with .msi install file. I read some information about creating uninstaller shortcut here: http://wixtoolset.org/documentation/manual/v3/howtos/files_and_registry/create_uninstall_shortcut.html , But i cant found information about make uninstall file after msi build , maybe whom know it's possible ? and if possible how i can do it ? or maybe it possible to do with cmd script? Just write script for automatically uninstall my program from mashine. My code is :
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"><?define WpfApp1_TargetDir=$(var.WpfApp1.TargetDir)?>
<Product Id="*" Name="SetupProject2" Language="1033" Version="1.0.0.0" Manufacturer="Andrejka" UpgradeCode="PUT-GUID-HERE">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<Property Id="WIXUI_INSTALLDIR" Value="TESTFILEPRODUCTDIR" />
<Property Id="WixShellExecTarget" Value="[#WpfApp1.exe]" />
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
<Property Id="LAUNCH_APP_ON_EXIT" Value="1" />
<InstallExecuteSequence>
<Custom Action='LaunchApplication' After='InstallFiles'/>
</InstallExecuteSequence>
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes"/>
<Feature Id="ProductFeature" Title="SetupProject2" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="TESTFILEPRODUCTDIR" Name="SetupProject2">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="SetupProject2" />
</Directory>
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<!-- TODO: Remove the comments around this Component element and the ComponentRef below in order to add resources to this installer. -->
<!-- <Component Id="ProductComponent"> -->
<!-- TODO: Insert files, registry keys, and other resources here. -->
<!-- </Component> -->
<Component Id="WpfApp1.exe" Guid="*">
<File Id="WpfApp1.exe" Name="WpfApp1.exe" Source="$(var.WpfApp1_TargetDir)WpfApp1.exe" />
</Component>
<Component Id="WpfApp1.exe.config" Guid="*">
<File Id="WpfApp1.exe.config" Name="WpfApp1.exe.config" Source="$(var.WpfApp1_TargetDir)WpfApp1.exe.config" />
</Component>
<Component Id="aws_sdk_net_core_support.dll" Guid="*">
<File Id="aws_sdk_net_core_support.dll" Name="aws-sdk-net-core-support.dll" Source="$(var.WpfApp1_TargetDir)aws-sdk-net-core-support.dll" />
</Component>
<Component Id="AWSSDK.Core.dll" Guid="*">
<File Id="AWSSDK.Core.dll" Name="AWSSDK.Core.dll" Source="$(var.WpfApp1_TargetDir)AWSSDK.Core.dll" />
</Component>
<Component Id="AWSSDK.SimpleNotificationService.dll" Guid="*">
<File Id="AWSSDK.SimpleNotificationService.dll" Name="AWSSDK.SimpleNotificationService.dll" Source="$(var.WpfApp1_TargetDir)AWSSDK.SimpleNotificationService.dll" />
</Component>
<Component Id="MimeSharp.dll" Guid="*">
<File Id="MimeSharp.dll" Name="MimeSharp.dll" Source="$(var.WpfApp1_TargetDir)MimeSharp.dll" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>
In general you are not supposed to put uninstall shortcuts in the start menu, it is in fact a violation of Microsoft's logo requirements for Windows applications I believe. Rather you should let people uninstall your product the normal way via the add/remove programs applet.
UPDATE: I found this answer with some more information on this topic: Shortcuts with name "Uninstall <Program Name>" are not displayed in Windows 8/8.1/10
Also, just so it is clear, uninstall, is a built-in feature of MSI files - it is always automatically available unless actively blocked (such as some applications hiding themselves from display in add/remove programs). There is nothing extra you have to do in your WiX sources to support uninstall properly. Just follow Windows Installer guidelines and it comes "for free".
If what you are asking is for a way to create an uninstall batch file, then you can find a plethora of ways to uninstall your MSI file in this "uninstall reference": Uninstalling an MSI file from the command line without using msiexec.
In short, just run the command line below to uninstall your MSI if you have the MSI's product code (you can find your product code by querying your system as described here: How can I find the product GUID of an installed MSI setup? - you might need to look it up since you auto-generate your product code):
msiexec.exe /x {your-product-guid}
or just uninstall by referring to your original MSI installation file like this:
msiexec.exe /x "c:\filename.msi
See the linked answer above (the uninstall reference) for a lot more information about this.
This question is asking whether one of the ICE57 validators creates a false positive error report.
I am using WIX 3.9 to generate an installer. I want a per machine installation with non advertised shortcuts.
This WXS example installs a text file and a shortcut to open the text file:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="ShortcutTest" Language="1033"
Version="1.0.0.0" Manufacturer="Widget Co"
UpgradeCode="--YOUR GUID1--">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes"/>
<Feature Id="ProductFeature" Title="ShortcutTest" Level="1">
<ComponentRef Id="TextFile" />
<ComponentRef Id="ShortCut" />
</Feature>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="ShortcutTest">
<Component Id="TextFile" Guid="--YOUR GUID2--">
<File Id="File" Name="TextFile.txt" Source="TextFile.txt" KeyPath="yes"/>
</Component>
</Directory>
</Directory>
<Directory Id="ProgramMenuFolder">
<Directory Id="ApplicationProgramsFolder" Name="Shortcut Test">
<Component Id="ShortCut" Guid="--YOUR GUID3--">
<RegistryValue Root="HKMU" Key="Software\WidgetCo\ReadMeTextFile\TextFile" Name="Installed" Type="string" Value="yes" KeyPath="yes"/>
<Shortcut Id="Shortcut"
Name="Open Text File"
Description="Opens a text file"
Target="[INSTALLFOLDER]TextFile.txt"
WorkingDirectory="INSTALLFOLDER"/>
<RemoveFolder Id="ApplicationProgramsFolder" Directory="ApplicationProgramsFolder" On="uninstall"/>
</Component>
</Directory>
</Directory>
</Directory>
</Product>
</Wix>
If you build the above example into an MSI package, you get this Internal Consistency Evaluator (ICE) error:
D:\Robert\Documents\Visual Studio 2013\Projects\ShortcutTest\Product.wxs(27,0): error LGHT0204: ICE57: Component 'ShortCut' has both per-user data and a keypath that can be either per-user or per-machine.
ICE57 is implying an inconsistency between per-user and per-machine data. But, the key path of the component is HKMU, which in a per machine installation resolves to HKLM (HKEY_LOCAL_MACHINE). The location of the shortcut derives from 'ProgramMenuFolder', which in a per-machine installation resolves to C:\ProgramData\Microsoft\Windows\Start Menu\ (on Windows 8.1). None of the component's resources appear to have any per-user association.
You can build the installer package into an MSI by suppressing ICE57. The resulting MSI package installs without any obvious errors. Multiple users can log on and access the shortcut. Any user can un-install the package and all of the resources in the package are removed.
The answer to Wix create non advertised shortcut for all users / per machine has an interesting workaround, which is to author advertised shortcuts and then turn off advertising. Seems a round about way of creating un-advertised shortcuts.
A common fix for the ICE57 error is to change the <RegistryValue...> root to HKCU (HKEY_CURRENT_USER). However this creates an installer that can leave a user registry key behind when un-installed. For example if user A installs the package, a registry entry is added to user A's registry hive. If user B removes the package, the registry entry is not removed from user A's registry hive.
In this scenario is the ICE57 error a bug in the Internal Consistency Evaluators? Or is there something I have miss-understood?
While researching another problem I found this comment on http://sourceforge.net/p/wix/mailman/message/26687047/ from Rob Mensching:
IIRC, this is a bug in ICE57. The Windows Installer team didn't look at
ALLUSERS property when evaluating these values... that was a long time ago
though so my memory may have decayed a bit.
It looks like a bug in ICE57.
Move your Shortcut to the be a child of File and add the Adversite="yes" attribute. The RegistryValue should do the trick for converting the shortcut from perUser to perMachine.
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="MyApp" />
</Directory>
<Directory Id="ProgramMenuFolder" Name="Programs">
<Directory Id="ApplicationProgramsFolder" Name="My App Name" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ComponentGroup_Core">
<Component Id="Component_App" Guid="INSERT_GUID_HERE" Directory="INSTALLFOLDER">
<RegistryValue Root="HKCU" Key="Software\[Manufacturer]\[AppName]"
Name="AppInstalled" Type="string" Value="yes" KeyPath="yes"/>
<File Id="MyApp" Name="My Test App.txt">
<Shortcut Id="Shortcut"
Name="Open Text File"
Description="Opens a text file"
Directory="ApplicationProgramsFolder"
WorkingDirectory="INSTALLFOLDER" />
</File>
</Component>
<Component Id="Component_MenuFolder" Guid="INSERT_GUID_HERE"
Directory="ApplicationProgramsFolder">
<RegistryValue Root="HKCU" Key="Software\[Manufacturer]\[AppName]"
Name="MenuFolderInstalled" Type="string" Value="yes"
KeyPath="yes"/>
<RemoveFolder Id="RemoveFolder_App" On="uninstall" />
</Component>
</ComponentGroup>
</Fragment>
I have my bootstrapper project and I need to add a shortcut only when another third part msi is selected on bootstrapper's UI. So I end up with another little msi like this (removing not relevant data):
<Wix >
<Product >
<Package />
<MajorUpgrade />
<MediaTemplate />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramMenuFolder">
<Directory Id="ApplicationProgramsFolder" Name="FolderName">
</Directory>
</Directory>
</Directory>
<Component Id="ApplicationShortcut" Guid="PUT-GUID-HERE" Directory="ApplicationProgramsFolder">
<Shortcut Id="ApplicationStartMenuShortcut"
Name="App"
Description="desc"
Target='"[ProgramFiles64Folder]Folder1\Folder2\app.exe"'
Arguments=' -n name'
/>
<RemoveFolder Id="RemoveProgramMenuDir" Directory="ApplicationProgramsFolder" On="uninstall" />
<RegistryValue Root="HKCU" Key="Software\ACME\App" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
</Component>
<Feature Id="ProductFeature" Title="Shortcuts" Level="1">
<ComponentRef Id="ApplicationShortcut" />
</Feature>
</Product>
But I get
ICE71: The Media table has no entries.
That source doesn't compile anyway because of issues with missing languages, productcodes and so on. It would have helped if you'd posted a complete working example. After fixing those issues and seeing ICE71, you basically need to delete mediatemplate and add a proper media entry such as (in angle brackets)
Media Id="1" Cabinet="product.cab" EmbedCab="yes"
then all you get is warning LGHT1079 : The cabinet 'product.cab' does not contain any files. If this installation contains no files, this warning can likely be safely ignored. Otherwise, please add files to the cabinet or remove it.
I would just augment the third party MSI with a transform that creates a shortcut when that MSI is installed. This way you don't have to do anything special in the bootstrapper.
I have a WiX installation that also needs to write some registry keys, and I was wondering if there's a way to tell WiX/MSI to
only create a key if it doesn't exist yet
always create/overwrite another key, even if it exists
I tried something like this:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="TestRegistry" Language="1033" Version="1.0.2"
Manufacturer="Myself" UpgradeCode="PUT-GUID-HERE">
<Package InstallerVersion="200" Compressed="yes"
InstallScope="perUser" InstallPrivileges="limited" />
<MajorUpgrade DowngradeErrorMessage="A newer version installed." />
<MediaTemplate EmbedCab="yes" />
<Feature Id="ProductFeature" Title="TestRegistry" Level="1">
<ComponentRef Id="ProductComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="dirManufacturer" Name="Manufacturer">
<Directory Id="INSTALLFOLDER" Name="TheProduct">
<Component Id="ProductComponents" Guid="*" DiskId="1">
<RegistryKey Root="HKCU" Key="Software\Manufacturer\TheProduct"
Action="createAndRemoveOnUninstall">
<RegistryValue Type="string" Name="Install Directory"
Value="[INSTALLFOLDER]" KeyPath="yes" />
<RegistryValue Type="string" Name="Product Version"
Value="[ProductVersion]" />
<RegistryValue Type="string" Name="Default Language" Value="en" />
<RegistryValue Type="string" Name="Web Site URL"
Value="https://product.manufacturer.info/" />
</RegistryKey>
</Component>
</Directory>
</Directory>
</Directory>
</Directory>
</Fragment>
</Wix>
and here, I'd like to always overwrite the Install Directory and Product Version keys with current values, but I would like to preserve other settings, like Default Language.
Is there any way to do this?
Right now, when I install 1.0.0 fresh on a new system, it creates the registry keys alright. When I uninstall it, they're gone - so far, so good.
But when I installed v1.0.1 and then - without uninstalling v1.0.1 - installed v1.0.2 on top of this, ALL the defined registry keys were updated and contained the default values defined in the WiX script - the changes I had made manually were wiped out.
You will need to break the registry values out to there own components and set the NeverOverwrite attribute on them
<Component Id="DefaultLangaugeComponent" Guid="*" NeverOverwrite="yes">
<RegistryKey Root="HKCU" Key="Software\Manufacturer\TheProduct"
Action="createAndRemoveOnUninstall">
<RegistryValue Type="string" Name="Default Language" Value="en" />
</RegistryKey>
</Component>
After installation of perUser msi package I cannot uninstall it.
When selecting (Browse) package - that I installed - there is an error: 'selected package is not valid package for this product'.
Here's my code:
<?xml version='1.0'?><Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
<Product Id='a871a539-5954-44b7-810d-caed5d09e4c5' Name='x' Language='1033'
Version='1.1.0.0' Manufacturer='M' UpgradeCode='a871a539-5954-44b7-810d-caed5d09e4c5'>
<Package Description='x'
Comments='x'
Manufacturer='x' InstallerVersion='200' Compressed='yes' InstallScope='perUser' />
<Media Id='1' Cabinet='product.cab' EmbedCab='yes' />
<Directory Id='TARGETDIR' Name='SourceDir'>
<Directory Id='AppDataFolder' Name='AppData'>
<Directory Id='xFolder' Name='x' />
</Directory>
</Directory>
<Component Id='xComponent' Guid='a871a539-5954-44b7-810d-caed5d09e4c5'
Directory='xFolder'>
<RemoveFolder Id="Removex" On="uninstall" />
<!-- registry entry to be used as keypath -->
<RegistryValue Root="HKCU"
Key="Software\M\x"
Name="component.xcomponent.installed"
Type="integer"
Value="1"
KeyPath="yes"/>
<File Id='myFile' Name='myFile.txt' DiskId='1' Source='myFile.txt' />
... files here
</Component>
<Feature Id='xFeature' Title='x feature' Level='1'>
<ComponentRef Id='xComponent' />
</Feature>
Installation process is ok - no errors. Files are in correct place. Registry key is added.
What am I doing wrong?
Yes - as Wim Coenen said - that question helped me resolve problem.
However instead of executing steps in that question I cleaned registry.
The problem was that I installed this package many times changing GUID and other parameters, so there was quite a mess in registry. I searched registry by Manufacturer and Name.
After cleaning up everything was ok.