重大升级回滚场景下,如何在RemoveExistingProduct后启动服务?
问题背景
现有安装程序的自定义操作序列:InstallInitialize(标准操作)→RemoveExistingProduct(标准操作)→若干自定义操作→StartService(标准操作)
在重大升级过程中,若StartService执行前触发回滚,RemoveExistingProduct会执行。操作完成后,应用服务已通过自定义操作启用,但未启动。
已尝试的方案及问题:
- 编写回滚自定义操作
Rollback_startService,按「InstallInitialize→Rollback_startservice→RemoveExistingProduct」调度时,RemoveExistingProduct标准操作抛出“序列错误”报错; StartService标准操作不会在RemoveExistingProduct标准操作流程中被调用;- 安装程序多处使用
UPGRADINGPRODUCTCODE属性,无法调整RemoveExistingProduct的调度位置。
需求:需通过StartService标准操作或Rollback_startService自定义操作启动服务,求最优解决方案。
最优解决方案
核心思路
利用MSI回滚序列的绑定规则,将Rollback_startService自定义操作与原StartService标准操作的回滚逻辑关联,同时通过精准条件限制,确保仅在重大升级回滚且服务已启用未启动的场景下触发,规避序列冲突问题。
具体步骤
定义
Rollback_startService自定义操作- 操作类型设为
19(msidbCustomActionTypeRollback+msidbCustomActionTypeInScript),标记为脚本化回滚操作,符合MSI序列执行规范。 - 操作逻辑:检查目标服务的启动类型与运行状态,若服务已启用(注册表
Start值为2/3)但未运行,则调用系统API启动服务。
- 操作类型设为
配置调度与执行条件
- 将
Rollback_startService放置在InstallInitialize之后、RemoveExistingProduct之前,添加执行条件:
(注:REMOVE="ALL" AND UPGRADINGPRODUCTCODE AND SERVICE_START_TYPE="2" OR SERVICE_START_TYPE="3"SERVICE_START_TYPE需提前通过自定义操作查询服务注册表项获取并存入属性) - 该条件确保仅在重大升级回滚、且服务已启用的场景下触发操作,避免干扰正常安装流程。
- 将
关联原
StartService的回滚逻辑- 为原
StartService标准操作指定回滚自定义操作为Rollback_startService,确保当StartService被回滚触发时,自动调用该自定义操作。
- 为原
关键注意点
- 保留
RemoveExistingProduct的原调度位置,兼容现有UPGRADINGPRODUCTCODE的多处使用; - 脚本化回滚操作类型可避免“序列错误”,符合MSI的执行顺序规则;
- 精准的条件判断可防止操作在非目标场景下执行,避免引发新的安装问题。
内容的提问来源于stack exchange,提问作者user-24
相关产品推荐
相关产品推荐

