【发布时间】:2017-03-06 20:12:30
【问题描述】:
我们正在将安装程序从 Visual Studio 安装程序项目 (*.vdproj) 升级到 WiX 安装程序。从我们用户的角度来看,我们希望使这种过渡尽可能无缝。 IE。如果他们拥有使用 *.vdproj 构建中的 MSI 安装的我们软件的 1.0 版,则使用 WiX 构建中的 MSI 安装的 v2.0 应该覆盖/删除旧版本并正常继续。
我们遇到的问题是,原来的 *.vdproj 安装程序将软件安装为“ALLUSERS=false”,而现在使用 WiX,我们想使用 InstallScope="perMachine"(即“ALLUSERS=true”)。
我们使用的是引导式 WiX 安装程序,其中链中的第一个元素处理 .Net Framework 安装(如有必要),第二个元素是我们产品的 MSI 安装程序。
<MajorUpgrade DowngradeErrorMessage="A newer version of ... is already installed." />
<Upgrade Id="{UPGRADE-CODE-OF-OLD-INSTALLER}">
<UpgradeVersion OnlyDetect="no" Property="OTHER_STUFF_FOUND" Minimum="0.0.0" />
</Upgrade>
如果我们在新的 WiX 安装程序中设置 InstallScope="perUser",那么这将按需要运行,但是如果我们设置 InstallScope="perMachine",则卸载失败并记录此错误:
MSI (c) (04:10) [23:18:49:626]: FindRelatedProducts: current install is per-machine. Related install for product '{PRODUCT-CODE-OF-OLD-INSTALLER}' is per-user. Skipping...
经过一些研究,我们了解到这是一个已知问题,并且无法像上面写的那样简单的解决方案,因为 Microsoft 安装程序会阻止上下文切换(即从 perUser 到 perMachine)。
问题是:我们如何以稳健的方式处理此升级?目前我们没有可行的解决方案。
我可以想到几个选项,但想看看人们是否有更好的答案、关于哪个选项最好的建议,或者关于如何实施这些列出的方法之一的建议:
- 使用自定义操作手动卸载旧软件或向用户发出警告以手动卸载旧版本并终止安装。如果我们知道旧安装程序的升级代码,我们应该可以搜索注册表,看看是否安装了旧软件?当我在重新查看时
- 我能否拥有第二个 WiX MSI 安装程序,以 InstallScope="perUser" 身份运行并单独负责删除旧安装?
- 我找到了这个解决方案[3],但是因为我们使用的是 Bootstrapped 安装程序,我们的 MSI 项目中的标签没有执行,所以它对我们不起作用。
- 将我们的新 WiX 安装程序更改为“perUser”并在未来某个时间处理此问题(不是理想的解决方案)
关于卸载旧的 perUser 安装。如果与最初用于按用户安装的用户相比,登录的用户不同,这似乎会出现问题?这里有什么我们应该注意的问题吗?
更新
我尝试了使用 CustomAction 的方法,在该方法中我使用升级代码调用 MsiEnumRelatedProducts 以查看是否安装了我们软件的先前版本,然后调用
msiexec /X {PRODUCT-CODE-FOUND-USING-MsiEnumRelatedProducts} \q
卸载旧版本。但是,这不起作用,因为似乎 MSI 使用互斥锁来确保一次只能执行一个 MSI 操作..
【问题讨论】: