4

我已经实现了一个没有任何依赖的自定义命令,没有任何问题。

但这里是一个自定义命令,需要与其他四个 dll 链接才能工作。

<Binary Id="libeay32"          SourceFile="..\bin\libeay32.dll"/>
<Binary Id="libintl"           SourceFile="..\bin\libintl.dll"/>
<Binary Id="libpq"             SourceFile="..\bin\libpq.dll"/>
<Binary Id="ssleay32"          SourceFile="..\bin\ssleay32.dll"/>
<Binary Id="custom"            SourceFile="..\bin\custom_cmd.dll"/>

  <CustomAction Id="cc_postgres" BinaryKey="custom" DllEntry="on_postgres_cmd" Execute="immediate" Return="check" HideTarget="no" />

安装时出现以下错误

错误 1723。此 Windows 安装程序包有问题。无法运行完成此安装所需的 DLL。请联系您的支持人员或软件包供应商。动作 cc_postgres,条目:on_postgres_cmd,库:C:\Users\THE\AppData\Local\Temp\MSI17BB.tmp

如何在 Wix 中进行此操作,而无需重新编译静态中的所有内容。

谢谢。

4

1 回答 1

4

MSI 不提供这些服务,WiX 也不提供这样做的扩展。我想你可以为此目的编写一个 WiX 扩展,但为什么呢?

MSI 运行您的类型 1 自定义操作,首先将二进制资源的副本提取到临时目录,然后调用该副本中的入口点,并(在完成自定义操作后)释放临时 DLL 副本。(或者不:MSI 可能会决定保留该副本一段时间,作为一种优化,以防您稍后要调用其他入口点。但这取决于 MSI,而不是您的代码。)

关键是二进制资源是临时自动加载的……而且只有一个资源。这意味着加载所需的任何其他资源取决于您的自定义操作。

作为第一步,您的自定义操作需要在Binary表上打开一个视图,从适当的记录中读取Data列作为流,然后将该数据缓冲区转储到某个文件中,然后执行显式::LoadLibrary(). 然后::GetProcAddress()在函数上,您的自定义操作将从加载的库中调用,并使用获取的指针进行显式调用。最后,由于您是一位有礼貌的程序员,当您的自定义操作完成后,它需要在返回之前拆除所有这些基础设施:释放视图和库句柄,删除临时文件等。

如果这一切看起来很麻烦,你是对的,它是。非常简单的解决方案正是您拒绝的解决方案:custom_cmd.dll静态链接。是的,这将使您的二进制文件和包含它的.msi稍微大一点(而且不会大很多,因为您可能不再需要依赖 DLL 的单独二进制副本)。但这几乎是唯一的缺点。好处是您的自定义操作会随身携带完成工作所需的一切。

我经常在安装时运行的任何二进制文件上做一个静态链接——不仅仅是自定义操作,还有引导程序等——即使它们没有明确的外部依赖关系。(但当然它们有隐含的,比如 Visual C++ 运行时库等。)这样,我不仅知道我有我需要的资源,而且知道这些资源的正确版本,而不是客户可能发生的任何版本以前安装...或根本没有安装。

你的安装包是一个不提前知道他的环境的侦察员。它可能是美国的一个大城市……或者它可能是月球。或巴苏姆。不要以为你会有手机服务……或氧气。随身携带!

于 2013-03-05T00:21:13.383 回答