You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Wix单用户转全用户安装后升级异常:添加/删除程序现双条目

Wix单用户转全用户安装后的升级问题解决方案

核心问题:单用户(perUser)和全用户(perMachine)的MSI属于不同安装上下文,Windows Installer会将二者视为独立产品,导致升级时出现双条目;修改快捷方式路径后升级失效,是因为上下文不匹配使得升级规则无法关联旧版本。

1. 统一核心标识与安装上下文

  • 保持UpgradeCode完全固定(这是关联新旧版本的唯一核心,跨上下文必须一致),每次升级时更换ProductCode(用Id="*"自动生成即可)
  • 在Product节点强制设置全用户上下文:
    <Product Id="*" UpgradeCode="固定的升级GUID" 
             InstallScope="perMachine" InstallPrivileges="elevated">
    

2. 配置升级规则强制卸载所有旧实例

在Product节点下添加覆盖所有安装上下文的升级规则,确保不管旧版本是单用户还是全用户,都会被卸载:

<Upgrade Id="固定的升级GUID">
  <!-- 匹配所有旧版本(perMachine) -->
  <UpgradeVersion Minimum="0.0.0.0" Maximum="你的新版本号" 
                  IncludeMinimum="yes" IncludeMaximum="no" 
                  Property="OLDVERSION_FOUND" MigrateFeatures="yes" />
  <!-- 单独匹配perUser的旧实例 -->
  <UpgradeVersion Minimum="0.0.0.0" Maximum="你的新版本号" 
                  IncludeMinimum="yes" IncludeMaximum="no" 
                  Property="OLDVERSION_FOUND_PERUSER"
                  Installed="yes" Scope="user" />
</Upgrade>

然后在执行序列中添加卸载动作,优先级必须在InstallInitialize之前:

<InstallExecuteSequence>
  <!-- 卸载perMachine旧版本 -->
  <RemoveExistingProducts Before="InstallInitialize" />
  <!-- 卸载perUser旧版本 -->
  <Custom Action="UninstallPerUserOld" Before="InstallInitialize">
    OLDVERSION_FOUND_PERUSER
  </Custom>
</InstallExecuteSequence>

配合WixUtilExtension添加自定义卸载动作:

<CustomAction Id="UninstallPerUserOld" 
              Execute="deferred" Impersonate="no"
              ExeCommand='msiexec.exe /x "[ProductCode]" /qn' />

3. 确保快捷方式的全用户路径正确

直接使用Wix内置的ProgramMenuFolder(对应C:\ProgramData的公共开始菜单),组件必须绑定HKLM注册表项(标记为全用户组件):

<DirectoryRef Id="ProgramMenuFolder">
  <Component Id="AppShortcut" Guid="组件GUID">
    <Shortcut Id="MainShortcut"
              Name="你的应用名称"
              Target="[INSTALLFOLDER]你的程序.exe"
              WorkingDirectory="INSTALLFOLDER" />
    <!-- 用HKLM注册表作为组件KeyPath,标记为全用户组件 -->
    <RegistryValue Root="HKLM" Key="Software\你的公司\你的应用" 
                   Name="Installed" Type="integer" Value="1" KeyPath="yes" />
  </Component>
</DirectoryRef>

4. 处理无法手动卸载的旧版本残留

如果旧版本手动卸载失败,添加预清理动作强制卸载:

<CustomAction Id="CleanupOldPerUser" 
              Execute="immediate" Impersonate="yes"
              ExeCommand='msiexec.exe /x "{旧版本ProductCode}" /qn /forcerestart' />
<InstallExecuteSequence>
  <Custom Action="CleanupOldPerUser" Before="InstallInitialize">
    NOT Installed AND EXISTS HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall\{旧版本ProductCode}
  </Custom>
</InstallExecuteSequence>

5. 验证安装包

编译后通过以下方式确认:

  • 运行msiexec /i 你的安装包.msi /lvx* install.log,查看日志中INSTALLSCOPE是否为perMachine
  • 检查注册表:全用户产品信息在HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall,而非HKCU

内容的提问来源于stack exchange,提问作者Johan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 21:30:26