如何正确调度WiX脚本自定义操作以在升级期间正常运行?
升级时Windows Installer脚本自定义操作找不到文件的问题解决
你的自定义操作序列配置如下:
<InstallExecuteSequence> <Custom Action="CallInstaller" Before="InstallFinalize"> <![CDATA[NOT Installed OR UPGRADINGPRODUCTCODE]]> </Custom> </InstallExecuteSequence>
1. 自定义操作调度是否错误?
是,核心问题出在执行时机与上下文:
- 你当前的自定义操作默认是即时(Immediate)执行,这类操作在Windows Installer开始修改系统(复制文件、写入注册表等)前运行。此时新版本脚本还未复制到目标文件夹,若为重大升级,旧版本文件可能已被
RemoveExistingProducts卸载,自然找不到脚本。 - 另外,
UPGRADINGPRODUCTCODE仅在重大升级的新产品安装流程中生效,若你用的是小升级/小型更新,这个条件可能无法触发,导致操作执行时机不对或直接不执行。
正确的配置需将自定义操作设为延迟(Deferred)执行,确保在InstallFiles之后、InstallFinalize之前运行,同时指定系统上下文(避免权限问题):
<InstallExecuteSequence> <Custom Action="CallInstaller" Before="InstallFinalize" Execute="deferred" Impersonate="no"> <![CDATA[NOT Installed OR UPGRADINGPRODUCTCODE]]> </Custom> </InstallExecuteSequence>
2. 脚本自定义操作的特殊限制
脚本类自定义操作有几个必须注意的限制:
- 路径不能硬编码:必须用Windows Installer的文件引用语法,比如
[#YourScriptFile.exe](YourScriptFile.exe是文件在MSI File表中的键值),确保引用的是当前安装版本的脚本,而非旧路径。 - 延迟操作的属性传递:延迟执行的操作无法直接访问大多数即时阶段的属性,若需获取
INSTALLDIR这类路径,要先在一个即时自定义操作中设置CallInstaller的CustomActionData为"INSTALLDIR=[INSTALLDIR]",再在脚本中通过Session.CustomActionData["INSTALLDIR"]读取。 - 权限与上下文:若脚本需修改系统资源,必须开启
Impersonate="no"以系统上下文运行,否则会因权限不足失败。
3. 为何自定义操作启动时目标文件夹无文件?
主要有三个原因:
- 执行时机过早:即时操作在文件复制前运行,此时新版本文件未到位,旧版本文件可能已被卸载,导致路径为空或文件缺失。
- 组件配置问题:即便组件Guid设为
*,若KeyPath设置错误、脚本文件版本未升级,Windows Installer会判定文件无需更新,跳过复制。确保脚本版本号高于旧版本,且组件KeyPath指向该脚本。 - RemoveExistingProducts位置不当:若重大升级中
RemoveExistingProducts设在InstallFinalize之后,自定义操作运行时旧版本文件仍存在,但新版本文件未完成覆盖,若脚本依赖新版本资源会直接失败。建议将RemoveExistingProducts放在InstallInitialize之后、InstallFiles之前,先卸载旧版本再安装新版本,确保操作运行时用的是新文件。
内容的提问来源于stack exchange,提问作者José Neto
相关产品推荐
相关产品推荐

