Unable to remove previous versions of MSI. Multipl

2020-02-07 08:00发布

问题:

I am not sure if i am missing something or i just plain dumb, the issue i am having related to uninstalling a MSI. Basically i am building a app, and using WIX to create the MSI installer. What is happening is that i am able to install a previous version of the app but not upgrade to a newer version MSI. E.g, when i click/install the newer version MSI then the older MSI, both MSI will be installed and visible in control panel(MyApp 1.5.0, MyApp 1.6.0).

I am pretty sure i have the "MINORUPGRADE/MAJORUPGRADE" along with the RemoveExistingProducts Action configured properly but this issue still happens.

I tried modifying the MINORUPGRADE/MAJORUPGRADE values and the RemoveExistingProducts property but still get the same behavior.

My WIX config looks like this (without the Directory/paths...)

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
  <Product Id="*" Language="1033" Manufacturer="MyApp" Name="MyApp $(env.APP_BASE_VERSION)" UpgradeCode="$(env.UPGRADE_CODE)"
    Version="$(env.APP_BASE_VERSION)">
    <Package Compressed="yes" InstallerVersion="200" InstallScope="perMachine" InstallPrivileges="elevated" Description="MyApp $(env.APP_VERSION) Installer"
      Comments="" Manufacturer="MyApp" />

    <Property Id="MsiLogging" Value="v!" />
    <MediaTemplate EmbedCab="yes" CompressionLevel="$(env.COMPRESSION_LEVEL)"/>
    <Icon Id="icon.ico" SourceFile="$(env.STATIC_RESOURCE_PATH)\icon.ico" />
    <Property Id="ARPPRODUCTICON" Value="icon.ico" />

    <Upgrade Id="$(env.UPGRADE_CODE)">
      <UpgradeVersion 
          Property="MAJORUPGRADE" 
          Minimum="0.0.0.0" 
          IncludeMinimum="yes" 
          Maximum="$(env.APP_BASE_VERSION)" 
          IncludeMaximum="no" 
          IgnoreRemoveFailure="no" 
          MigrateFeatures="yes" /> 
        <UpgradeVersion 
          Property="MINORUPGRADE" 
          Maximum="$(env.APP_BASE_VERSION)" 
          Minimum="$(env.APP_BASE_VERSION)" 
          IncludeMinimum="yes" 
          IncludeMaximum="yes" 
          /> 

    </Upgrade>  


    ...

    <CustomAction Id="Remove_Roaming_MyApp" Directory="TARGETDIR" ExeCommand="cmd.exe /C &quot;rmdir /s /q &quot;[AppDataFolder]\MyApp&quot;&quot;" Execute="deferred" Return="ignore" HideTarget="yes" Impersonate="no" />

    <Property Id="WixShellExecTarget" Value="[#MyAppEXE]" />
    <CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />

    <util:CloseApplication Id="CloseApp"  Target="MyApp.exe" RebootPrompt="no" CloseMessage="yes"/>

    <CustomAction Id="Kill_MyApp_instances"
      Directory="TARGETDIR" 
      ExeCommand="taskkill.exe /IM MyApp.exe /F"
      Execute="deferred" 
      Return="ignore" HideTarget="yes" Impersonate="no" />

    <!-- This will create a log in the Temp folder of the user profile by default. NOTE: this is not the full log! The MSI will need to be ran with `/l*v <destination file>` -->
    <CustomAction Id="CopyLog_partial"
      ExeCommand="cmd /c copy &quot;[MsiLogFileLocation]&quot; &quot;%SystemDrive%\Windows\Temp\MyApp-msi.log&quot;" 
      Directory="TARGETDIR" 
      Impersonate="no" 
      Execute="commit" 
      Return="ignore" />
    <CustomAction Id="CopyLog_full"
      ExeCommand="cmd /c copy &quot;[MsiLogFileLocation]&quot; &quot;[LocalAppDataFolder]\Temp\MyApp-msi.log&quot;" 
      Directory="TARGETDIR" 
      Impersonate="no" 
      Execute="immediate" 
      Return="ignore" />
    <InstallExecuteSequence>

      <RemoveExistingProducts Before="InstallValidate" />
      <Custom Action="WixCloseApplications" Before="InstallValidate" /> 
      <Custom Action="Kill_MyApp_instances" After='InstallInitialize'></Custom>
      <Custom Action="LaunchApplication" After='InstallFinalize'>NOT Installed</Custom>

      <Custom Action="CopyLog_partial" After="PublishProduct" /> 
      <Custom Action="CopyLog_full" OnExit="success" />
    </InstallExecuteSequence>

    <Feature Id="ProductFeature" Title="SetupProject1" Level="1">
      <ComponentGroupRef Id="ELECTRON_FRAGMENTS"/> 
      <ComponentRef Id="Remove_MyApp_Roaming_comp" />
      <ComponentRef Id="Remove_uninstallCache_folder" />
      <ComponentRef Id="Remove_MyApp_programFiles_comp" />
      <ComponentRef Id="Shortcut_startMenu" />
    </Feature>

  </Product>
</Wix>

The intended behavior is to remove the previous MSI or better yet all versions installed during the installation process of the MSI. I know this can be done with a CustomAction but i was wondering if theres a more elegant way to do this?

回答1:

Summary: When you get two entries in Add / Remove Programs the major upgrade has failed. I suggest you comment out all major upgrade constructs and try to get a heartbeat with the simplest constructs available - explained below.


Major Upgrade: You have used old constructs to implement your major upgrade. There is a newer and simple way, like this:

<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />

This is sort of like a "template" implementing the major upgrade with the least amount of fuzz by just using "normal options" or simplified options if you like. There is no need to add your own RemoveExistingProducts entry when you use this template, in fact that will probably yield a "duplicate entry / symbol" on compile:

  • Add the MajorUpgrade element above.
  • Comment out the entire Upgrade element.
  • Comment out the RemoveExistingProducts element.

Older Constructs: The MajorUpgrade element will be enough to implement a working major upgrade, but you can still use the old WiX constructs (Upgrade and UpgradeVersion elements) to obtain more fine-grained control of the authoring of the Upgrade table. It is this table which defines how existing installations are to be handled. The upgrade table identifies related products by matching upgrade codes and then performs whatever action is defined for that scenario in the Upgrade table itself.

Previous Answers: There are several older answers on this topic, please see the following:

  • Doing Major Upgrade in Wix creates 2 entries in Add/Remove Programs
  • Adding entries to MSI UpgradeTable to remove related products (this shows how to use both the newer template construct AND the older WiX element for "fine-grained" control of Upgrade table).

A Few More Links:

  • Upgrading a WiX generated package with major version zero
  • How to prevent Wix from installing an older version?
  • Wix UpgradeVersion
  • Checking for Oldies

UPDATE:

  • Unable to remove previous versions of MSI. Multiple entry's show up in control panel
  • WIX does not uninstall older version (potential causes of failed major upgrade)