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

自定义Action导致MSI升级失败的问题排查求助

升级场景下延迟自定义动作执行失败的问题分析与解决

核心差异:升级与全新安装的执行上下文

  • 属性解析时机:延迟自定义动作的所有属性(如INSTALLFOLDER)会在即时执行阶段提前解析,而非动作实际运行时。升级时,INSTALLFOLDER指向新版本路径,但该路径在动作调度时还未被创建。
  • 文件夹创建逻辑:全新安装时,Windows Installer会在InstallFiles阶段创建包含文件的目标文件夹;但升级场景中,若新版本组件无实际文件(仅注册表、环境变量等),目标文件夹不会自动创建,导致动作执行时路径不存在。
  • 序列执行顺序:你的RemoveExistingProducts在InstallInitialize前执行,旧版本被完全卸载后,新版本的资源部署(含文件夹创建)要到InstallFiles阶段才启动,而原自定义动作调度在InstallFinalize前,时机早于文件夹创建。

问题根因

从升级日志的Error 1721可以明确:自定义动作的工作目录C:\Program Files\My Program 0.1.1\尚未创建。原因在于你的MainExecutable组件仅包含注册表、环境变量和卸载时的文件夹删除逻辑,没有触发文件夹自动创建的条件(无文件或显式创建指令),导致动作执行时路径不存在。

解决方案

1. 强制创建新版本目标文件夹

在INSTALLFOLDER对应的组件中添加CreateFolder元素,让Windows Installer在安装阶段主动创建该文件夹:

<Component Id='MainExecutable' Guid='something' Win64='yes'>
    <CreateFolder /> <!-- 新增:强制创建文件夹 -->
    <RemoveFolder Id='ProgramFiles64Folder' On='uninstall' />
    <Environment Id="PATH" Name="PATH" Value="[INSTALLFOLDER]something" Permanent="no" Part="last" Action="set" System="yes" />
    <RegistryKey Id='MyInstallDir' Root='HKLM' Key='somekey' ForceCreateOnInstall='yes' ForceDeleteOnUninstall='yes' >
        <RegistryValue Type='string' Name='InstallDir' Value='[INSTALLFOLDER]' Action='write' />
    </RegistryKey>
</Component>

2. 调整自定义动作的执行时机

将自定义动作调度到InstallFiles之后,确保文件夹已完成创建:

<InstallExecuteSequence>
    <RemoveExistingProducts Before="InstallInitialize" /> 
    <Custom Action="MyCustomAction" After="InstallFiles">
        <![CDATA[NOT Installed OR UPGRADINGPRODUCTCODE]]>
    </Custom>
</InstallExecuteSequence>

3. 修复延迟动作的属性传递(可选)

如果自定义动作依赖的INPUTFOLDER是即时属性,需通过CustomActionData传递给延迟动作(延迟动作无法直接访问即时属性):

步骤1:创建即时动作设置属性数据

<CustomAction Id="SetMyCustomActionData" Execute="immediate" Property="MyCustomAction" Value="INPUTFOLDER=[INPUTFOLDER]" />

步骤2:调整序列顺序

<InstallExecuteSequence>
    <RemoveExistingProducts Before="InstallInitialize" /> 
    <Custom Action="SetMyCustomActionData" Before="MyCustomAction">
        <![CDATA[NOT Installed OR UPGRADINGPRODUCTCODE]]>
    </Custom>
    <Custom Action="MyCustomAction" After="InstallFiles">
        <![CDATA[NOT Installed OR UPGRADINGPRODUCTCODE]]>
    </Custom>
</InstallExecuteSequence>

验证方法

修改后重新生成MSI,执行升级并查看日志:

  • 确认日志中存在CreateFolder针对INSTALLFOLDER的执行记录
  • 确认CustomActionSchedule中的Source路径已存在
  • 确认自定义动作返回值为1(执行成功)

内容的提问来源于stack exchange,提问作者José Neto

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 16:41:00