问题描述
我们的托管引导程序安装程序的用户应该能够在新版本导致问题的情况下降级捆绑包:
<MajorUpgrade Schedule="afterInstallValidate" AllowDowngrades="yes" AllowSameVersionUpgrades="no" />
升级时,现有的包被正确卸载。 程序和功能的已安装程序列表中仅保留新版本。日志确认选择的操作:
OnDetectRelatedBundle(): Operation MajorUpgrade
OnDetectRelatedBundle(): RelationType Upgrade
Planned package: APP_MSI_PACKAGE,state: Absent,default requested: Present,ba requested: Present,execute: Install,…
Planned related bundle: { },type: Upgrade,… execute: Uninstall,rollback: Install,dependency: None
降级时,现有捆绑包仍保留在程序和功能中。根据日志,类型降级被识别,但没有卸载计划:
OnDetectRelatedBundle(): Operation Downgrade
OnDetectRelatedBundle(): RelationType Upgrade
Planned package: APP_MSI_PACKAGE,state: Obsolete,default requested: None,ba requested: None,execute: None,…
Planned related bundle: {},type: Upgrade … execute: None,rollback: None,dependency: None
程序和功能中的同一个应用程序不应有两个条目。降级后,我可以手动卸载过时的版本,但用户不必这样做。
我觉得 MajorUpgrade
是 <Product>
的一部分令人困惑,但随后在程序和功能中跟踪整个包的版本。我在某处读到应该在 Product
和 Bundle
中使用相同的 UpgradeCode。那是推荐的吗?我尝试了相同的 UpgradeCode 和单独的 UpgradeCode。好像没什么区别。
我研究了一下,据说降级时不支持卸载。真的吗? 如果不支持,如何从托管引导程序代码手动触发相关包的卸载?
确实,问题归结为程序和功能中的双重输入。如果我无法卸载它,我是否可以通过其他方式通过代码删除(或者可能隐藏,我认为这是一个可怕的黑客攻击)捆绑包的过时版本?
解决方法
我必须使用事件 DetectRelatedBundle
确定安装程序是否安装了降级。然后在 PlanRelatedBundle
的事件处理程序中,我必须指定相关的包应该不存在:
private void OnPlanRelatedBundle(object sender,PlanRelatedBundleEventArgs e)
{
if (BundleUpgrade || BundleDowngrade)
e.State = RequestState.Absent;
}
为了更好的衡量,我在检测到升级时也设置了不存在状态,即使这种情况已经有效。现在在这两种情况下都删除了相关的包。