基本上我有两个关于安装的自定义操作:一个叫做CommitCA,一个叫做InstallCA.执行计划如下:
<CustomAction Id="CommitCA" BinaryKey="CustomActionDll" DllEntry="CommitCA" Execute="commit" Return="check" Impersonate="no"/> <CustomAction Id="InstallCA" BinaryKey="CustomActionDll" DllEntry="InstallCA" Execute="deferred" Return="check" Impersonate="no"/>
我已经从ORCA验证,在编译的安装程序中,CommitCA是在InstallCA之前安排的. CommitCA的类型是3585,InstallCA是3703(我找不到对它们的引用,但我假设一个用于提交操作,另一个是像我声明的那样的延迟操作).想法是在CommitCA中它将生成一些将由InstallCA使用的文件.
我的InstallCA的结构如下所示:
Try ' Do some work ... Catch ex As Exception ' Log the failure into installation log Return ActionResult.Failure End Try Return ActionResult.Success
这里有一个令人困惑的部分:最初我有一个工作版本,我没有在Catch块中返回ActionResult.Failure的行.换句话说,该函数仍然记录失败,但即使抛出异常,最终也会返回Success.我发现它有点误导,因为有时当异常发生并检查日志时,它表示自定义操作成功.这就是为什么我添加了这条线
Return ActionResult.Failure
但是,现在它不再起作用了!每当我安装时,我发现我的CommitCA永远不会被执行.注意:不是InstallCA,它具有我做的唯一代码修改,而是CommitCA,它实际上是在InstallCA之前安排的.当我说“永远不会被执行”时,我的意思是我找不到任何我放入函数调用的日志条目,并且MMSIBREAK环境变量甚至根本不起作用(窗口通知我附加到rundll32进程)永远不会弹出).但是下面的InstallCA仍然会被执行.
如果我注释掉Return ActionResult.Failure行,那么一切都会再次起作用:我可以附加进入CommitCA并调用InstallCA.
可能有些东西我误解了自定义操作的返回结果.我不应该在这种情况下返回ActionResult.Failure吗?但实际上我也在其他地方返回ActionResult.Failure.实际上在CommitCA函数本身中,我使用了相同的结构:在Catch块中返回ActionResult.Failure.所以有人能告诉我我做错了什么吗?
Installation Phases and In-Script Execution Options for Custom Actions in Windows Installer
关于提交CA的一些事情要理解:
提交自定义操作通常不是为了更改计算机的状态.它们用于清理回滚临时数据.
如果禁用回滚(通过属性或系统策略),则不会执行提交自定义操作,因为这意味着没有要清理的回滚数据.
偶尔提交自定义操作用于在无法执行回滚时配置计算机,并且您希望将更改推迟到尽可能晚. (更改用户密码,将DLL安装到GAC)在这些方案中,成本计算应指示延迟的自定义操作执行工作,因为回滚/提交永远不会执行.
应在延迟自定义操作之前安排回滚自定义操作,并且应在延迟自定义操作之后安排提交操作.这样脚本生成阶段就可以正确地创建脚本.
如果延迟阶段失败,则向后移动脚本以执行回滚.
如果所有延迟阶段都成功,则执行提交脚本.这意味着所有提交的CA必须在任何提交执行之前完成.