无法删除以前版本的 MSI。控制面板中出现多个条目

Unable to remove previous versions of MSI. Multiple entry's show up in control panel

我不确定我是否遗漏了什么或者我只是愚蠢,我遇到的问题与卸载 MSI 有关。基本上我正在构建一个应用程序,并使用 WIX 创建 MSI 安装程序。发生的事情是我能够安装以前版本的应用程序但不能升级到更新版本的 MSI。例如,当我 click/install 较新版本的 MSI 然后较旧的 MSI 时,两个 MSI 都将被安装并在控制面板中可见(MyApp 1.5.0,MyApp 1.6.0)。

我很确定我已经正确配置了 "MINORUPGRADE/MAJORUPGRADE" 和 RemoveExistingProducts 操作,但这个问题仍然存在。

我尝试修改 MINORUPGRADE/MAJORUPGRADE 值和 RemoveExistingProducts 属性 但仍然得到相同的行为。

我的 WIX 配置如下所示(没有 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>

预期的行为是删除以前的 MSI 或更好但在 MSI 安装过程中安装的所有版本。我知道这可以通过 CustomAction 来完成,但我想知道是否有更优雅的方法来做到这一点?

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.


重大升级:您已经使用旧结构来实施您的重大升级。有一种更新更简单的方法,像这样:

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

这有点像 "template" 通过使用 "normal options" 或简化选项(如果您愿意)以最少的模糊实现主要升级。使用此模板时无需添加您自己的 RemoveExistingProducts 条目,事实上这可能会在编译时产生 "duplicate entry / symbol":

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

Older ConstructsMajorUpgrade element 足以实现一个正在进行重大升级,但您仍然可以使用旧的 WiX 构造(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 本身。

以前的回答:关于这个话题有几个较早的回答,请看下面:

  • (这显示了如何使用较新的模板构造和较旧的 WiX 元素来 "fine-grained" 控制升级 table ).

更多链接:

  • Upgrading a WiX generated package with major version zero
  • Wix UpgradeVersion
  • Checking for Oldies

更新:

  • (重大升级失败的潜在原因)