使用WiX和C#管理依赖困境

4
我们即将推出产品,但在最后一刻,我被大量崩溃报告淹没,这些报告似乎与我们的安装程序有关。该安装程序是一个 WiX3 项目,具有 x86 和 x64 构建的单独输出。这些一直是个问题,我曾经认为已经修复,但最终发现它们仍然存在。
该产品本身是一组二进制文件,通过 .Net 远程通信相互通信,包括一个 Windows 服务和一个作为其他应用程序插件加载的小型 COM 组件。服务以 SYSTEM 运行,COM 部分以低权限上下文运行,而其他部分以普通用户上下文运行。其他部分包括第三方 COM 对象库 DLL 和带有 .net Remoting 接口的共享 DLL。
我观察到 MSI 的行为非常奇怪,特别是在版本升级时。由于微软强名称实现的严格要求(具体来说,在加载给定程序集之前进行精确版本检查),WiX/MSI 存在一个已记录的 bug,会在升级时擦除关键文件(如果升级 MSI 中的文件与现有安装的版本号相同,则删除该文件)。此外还必须解决 Wow64 虚拟化的问题(x86 MSI 只能通过 Wow64 写入注册表/硬盘位置,而 x64 MSI 无法在 x86 计算机上运行...)。我已经准备放弃整个系统并将其移植到其他安装系统。
我正在寻找有关技巧、技术或建议的提示,以便正确地完成任务,避免与 Windows Installer 扭曲的逻辑作斗争。我已经厌倦了与 WiX/MSI/Windows Installer 的斗争。它所需要做的就是按照我的指示放置文件和注册表键,适当时升级它们,并在用户卸载之前不删除任何内容。但实际情况是,依赖项随意被删除,引发一系列无法捕获的异常(无法在函数声明周围包装 try{} 块),使整个应用程序崩溃。
我特别感兴趣的是有关共享和依赖 DLL 的最佳实践和示例,以及确保如果需要将文件放入 GAC,则确实将其放入 GAC 并在适当时删除它的任何提示。
谢谢!
Tom

你将这个发到 WiX 邮件列表了吗? - JasonS
你知道吗,说实话我不知道。这个想法不错。 - Tom Corelis
你说你遇到了一个“WiX/MSI文档中记录的错误,会在升级时擦除关键文件”。你能提供一下相关文档的链接吗? - Wim Coenen
我似乎记得一段时间前读到过这种行为,尽管我现在找不到链接,也记不清它是MSI还是WiX的问题。我暂时会撤回那个说法。目前我能提供的最好证实是,我个人观察到升级包含合并模块时会发生这种情况。 - Tom Corelis
2
这是一个MSI的错误,而不是WiX的错误:http://support.microsoft.com/kb/905238 - Bob Arnson
3个回答

3

首先阅读 Windows Installer 完全指南

完成了吗?太好了。现在考虑放弃你现有的安装程序,从头开始并为所有你目前需要“解决”的东西提交一个应用程序错误报告。几乎每一个“扭曲逻辑”都是有目的的,目的是使您的安装更加可靠和可修复。

如果你不想要 Windows Installer 的可靠性和韧性,或者如果你试图以任何方式绕过它,那么使用其他东西。Windows Installer 做得比“只把文件和注册表键放在我告诉它的地方”多得多。

当你编写 MSI 包时,你定义了目标系统的外观。这是安装后的外观,如果删除了文件或关键数据文件损坏,它应该自动修复。你定义了系统在用户稍后取消从 1.0 升级到 2.0 期间应如何回滚。Windows Installer 是100% 数据驱动。从开发的角度来看,这是最难理解的概念,你不能仅仅编辑一个配置文件或编写一些更多的数据并期望它持久化。一旦你明白了这一点,Windows Installer 就变得非常简单了,你会设计你的程序和功能来在其限制内工作,而不是试图摆脱它们 :)

其他几个有用的链接...


我认为我理解的比你想象的要多。我真的很喜欢MSI的声明式工作流程...真的。对于复杂的安装,MSI应该正是如此...易如反掌。我会讨厌自己编写复杂安装场景的逻辑。媒介的限制足以让一个已经备受折磨的程序员发疯,更重要的是,当一个人的“声明”被不一致地遵循时,这会令人愤怒。这些是我的OP所面临的问题。 - Tom Corelis
我添加了几个链接,提供一些有用的阅读材料。 - saschabeaumont

1
假设您至少使用的是Wix 3.0,您可以利用MakeSfxCA.exe将依赖项打包到单个DLL中。(这是DFT - 部署工具基础结构的附加组件。)基本上,首先确保项目正在复制您的相关DLL。创建一个CustomAction.config文件。使用简单的.bat文件进行测试,例如:
REM MyMakeSfxCA.bat - 在$(TargetDir)下运行;需要绝对路径。 "%WIX%\SDK\MakeSfxCA" ^ %cd%\Managed_custom_action_pkg.dll ^ "%WIX%\SDK\x86\sfxca.dll" ^ %cd%\Managed_custom_action.dll ^ %cd%\Dependent1.dll ^ %cd%\Dependent2.dll ^ %cd%\Microsoft.Web.Administration.dll ^ %cd%\Microsoft.Deployment.WindowsInstaller.dll ^ %cd%\CustomAction.config
一旦完成,将其转换为后期构建事件: "$(WIX)\SDK\MakeSfxCA" ^ $(TargetDir)\Managed_custom_action_pkg.dll ^ "$(WIX)\SDK\x86\sfxca.dll" ^ $(TargetDir)\Managed_custom_action.dll ^ $(TargetDir)\Dependent1.dll ^ $(TargetDir)\Dependent2.dll ^ $(TargetDir)\Microsoft.Web.Administration.dll ^ $(TargetDir)\Microsoft.Deployment.WindowsInstaller.dll ^ $(TargetDir)\CustomAction.config
在您的.wxs文件中,二进制密钥看起来像: < Binary Id="Managed_custom_action_CA_dll" SourceFile="$(var.Managed_custom_action.TargetDir)$(var.Managed_custom_action.TargetName)_pkg.dll" / >
对于CustomAction.config,您可以在网上找到示例。
这是我发现处理托管代码时最好的方法。

-1

我有点害怕涉足这个领域,但只有在上游遵循最佳实践时才会出现限制。

以“删除文件”“错误”为例。我已经有一段时间没有看到这个问题了,但如果我回忆起来,通常是由以下情况引起的:

构建A: 文件1:1.0.0.0

构建B: 文件1:1.0.0.0

现在你进行了一次重大升级,在CostFinalize之后安排了RemoveExistingProducts。FindRelated Products检测到要删除的ProductCode,Costing说:“哦,我看到我有1.0.0.0,但1.0.0.0已经安装了,所以我在这里没什么可做的”,然后RemoveExistingProducts过来删除旧版本,从而删除file1。

我总是通过比Microsoft建议的更早地安排RemoveEXistingProducts来解决这个问题。这对我多年来一直有效。

至于依赖关系混乱,我管理一个软件产品线,其中包含数百个功能,由数百个合并模块和数千个文件(15,000+)表示,被数十个安装程序在各种特性、集成、主要、维护和维护_integ分支上使用。

我该怎么做呢?一次一个片段,大量的自动化、SCM和虚拟机来确保一切都按照预期工作。

在你的产品即将上市之际,我唯一能真正提供的“答案”就是让你知道像我这样的人随时可以被雇佣。你会惊讶于我们中的一些人能够多快地完成项目并推出软件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接