-
请原谅下面列出的“小事”。其中很多可能是平庸的,但也许可以使用列出的参数为自己提供理由,以避免自定义操作并致力于更好的解决方案 - 通常涉及更智能的应用程序启动顺序和应用程序自配置。相信我们,应用程序编码将比处理 Windows 安装程序的复杂调节、排序和模拟自定义操作更有趣。
-
下面的内容已经更新了很多次,部分内容有点乱序或到处重复。时间允许的情况下将进行清理。
-
开发人员擅长编码 - 因此恕我直言 - 您倾向于过度使用自定义操作做一些更好的事情内置 MSI 功能 or 现成的 MSI 扩展解决方案例如 WiX 中可用于高级功能的功能,例如XML 文件更新, IIS, COM+, 防火墙规则, 驱动安装, 自定义许可对于磁盘和注册表项,修改NT权限等等...这种支持也存在于商业工具中,例如Installshield和Advanced Installer。
-
还可以将自定义操作中完成的许多操作作为应用程序的启动顺序。最好的例子是初始化用户数据并将设置文件复制到每个用户配置文件。这里有一个关于这个问题的小总结:从管理员配置文件中在当前用户配置文件上创建文件夹和文件.
-
这是显而易见的,但很多时候,由于不了解通过现成解决方案“开箱即用”的可用内容,因此使用了自定义操作。这种事经常发生在我们所有人身上,不是吗?总有一些更聪明的方法可以让你避免很多悲伤?无论如何,总的来说——尽管有时你正在开辟新天地。不要在您的设置中开辟新天地 - 除非绝对必要!将其保存以供您的应用程序使用。
-
我想强调的是这些内置的 Windows Installer 解决方案以及 WiX 和商业工具的扩展是由现有的最佳部署专家编写的。此外,更重要的是,它们的内置 MSI 功能已被数千、数百万人(甚至数十亿人)使用和测试。你真的认为你可以做得更好吗?这个故事的寓意是:选择你的战斗并利用你出色的编码技能来解决新问题,并且让部署尽可能简单。使用已经有效的方法,不要重新发明轮子。部署中有太多的未知数,太多无法控制的变量——你正在处理“任何机器" in "任何州“并且在”任何语言". 请参阅此处的部署复杂性部分如果您想要示例(在页面下方一点),只需简短转储一下当您的包命中目标系统时其状态可能有所不同的所有方式。每个变量都是自定义代码的新熊陷阱 - 来自操作系统版本, to 应用地产 to 恶意软件情况. 这个清单还在不断地增加。正如链接内容中的结论所示:“部署是一个简单的概念,具有复杂的变量组合,可能会导致最神秘的错误 - 包括开发人员最喜欢的错误:间歇性错误。众所周知,此类错误的严重性怎么强调都不为过,因为它们通常无法正确调试。"
-
某些高级的事情必须在您的设置中完成 - 因为它们需要提升的权利并且您的应用程序在运行时不应请求此操作。这就是设置的目的,先进的、提升的系统配置 - 所以接受这种复杂性,但使用现成的解决方案!不要推出自己的脚本和解决方案,而使用内置的、经过良好测试的东西。你的脚本在韩国能正确运行吗?您的自定义操作是否会被您从未有时间测试脚本的主要反恶意软件解决方案阻止?您是否有时间编写自己的检查来检查计算机上是否安装了某个必备运行时 - 该运行时适用于所有区域设置和所有操作系统版本?这里出现错误的可能性是惊人的 - and 有时无法正确测试。你们有阿拉伯语、中文、韩语或日语的测试机吗?也许你会。但是您有终端服务器可供测试吗?韩国终端服务器怎么样?您是否使用 MSI 广告测试了您的设置?为了使高级系统管理功能发挥作用,您必须使您的设置尽可能简单和标准. 我想说,在你自己写任何东西之前,先花几天时间寻找现成的解决方案。请记住,使用现成的解决方案,您不仅仅是借用他们的代码,更重要的是借用其创建者的 QA、测试和 UAT - 您几乎永远不会希望重复这些。
-
真实世界测试是唯一重要的标准——没有替代品。不要承受这个痛苦的世界!通过 Windows 更新部署的 Windows 中的微小更改和您的自定义操作会以多种方式中断。选择更好的战斗来发挥你的技能。如果你反对设计,Windows 安装程序就会反击。
-
部署过程中发生了很多事情,这使得它变得复杂——而不是像我们想要的那样愚蠢(只需复制一些该死的文件),你的斗争是让它尽可能简单,但不能更简单。以下是部署任务列表,显示了为什么很难让您的包“足够愚蠢”:安装程序的好处和真正目的是什么?尽可能只使用现成的结构 - 这是第一个轻松的胜利。您所需要做的就是稍微阅读和搜索一下。
-
最后我要补充一点,所有自定义操作都应该支持回滚如果安装失败,将系统恢复到原始状态。在现实世界中,这几乎从未在临时自定义操作中完成(根据我的经验)。相信我,处理起来很复杂 - 我害怕“回滚”这个词,就像我在 C++ 中实现 MSI 回滚后,西伯利亚哈士奇害怕“洗澡”这个词一样。这不是我经历过的最有趣的事情,但它最终工作正常。如果您希望您的设置没有太多依赖项,那么 C++ 是最佳选择,而且众所周知,处理起来并不简单。现成的解决方案支持开箱即用的回滚 - 只需一点阅读和搜索即可轻松实现它们。是的,复杂,但你的基础更坚实。至关重要的是:一旦日本机器上发生了不起眼的错误,我们可以寻求社区修复,或者第三方供应商需要对其进行排序。
-
经过所有这些“一般观察”,在纯粹的技术层面上,Windows Installer 中的自定义操作在以下方面非常复杂:执行, 调度, 调理 and rollback,因此应该在绝对必要时使用(通常用于早期采用者的东西)。进一步的复杂性是运行时要求- 例如对特定版本的 .NET 运行时、PowerShell 或 Installscript 运行时的依赖性(Installshield 的脚本语言 - 它具有运行时依赖性,但这现在已基本解决,它曾经是一个问题)。
-
错误来自缺少运行时要求可能是一个巨大的毛团需要处理 - 对于零增益。由于这个原因我只使用最小依赖 C++ dll or 安装脚本进行自定义操作时。碰巧我使用VBScript or JavaScript for 用户界面序列中的只读自定义操作。这些只是检索数据,不会对系统进行任何更改。这些是唯一不易出错的自定义操作类型。然而,它们应该设置为在不检查退出代码的情况下运行(以防止它们在正在运行的设置中触发回滚或中止 - 通常在主要升级模式下)。
-
另外:Windows Installer 拥有自己的脚本运行时引擎,因此您知道活动脚本(VBScript、Javascript 等)可以运行,除非您的目标系统实际上已损坏(正常系统上不会缺少运行时)。这与托管代码自定义操作- 此时目标系统完全有可能没有 .NET 运行时(2018 年 1 月)。现在,这种情况将来会发生变化,因为 .NET 成为 Windows 中真正内置且必需的功能(或者由 Windows Installer 本身托管的某些最小版本)。托管自定义操作代码仍然存在因奇怪原因而失败的问题 - 例如使用了错误的 .NET 版本运行它,或者加载的 CLR 版本错误以及被利用等等……我在这里的经验有限,但我认为问题很严重。不过,我认为最终我们都会编写托管代码自定义操作。不过,我仍然会使用 C++ 进行全球分发场景。
-
Powershell 脚本对于自定义操作尤其复杂因为它们显然耗尽了进程并且无法访问 MSI 的会话对象(来源:MSI 专家 Chris Painter)。 Powershell 还需要安装 .NET 框架。我永远不会使用 Powershell 脚本进行自定义操作 - 甚至不会用于内部、公司部署。你的来电。作为一个“样本”,这里是该领域的一位专家陈述他的观点(老化的博客项目,但如果你问我的话仍然相关):不要使用托管代码来编写自定义操作!
-
我试着写一个不同自定义操作类型的优缺点总结。坦白说,我对此不太满意,但事实是:使用 WIX,Windows Installer 在 Windows 10 上失败,但在 Windows 7 上失败。我有什么不满意的?推荐 JavaScript 的原因之一是——我很少使用它,尽管它是一种比 VBScript 更好的语言——特别是在错误处理方面——但我在使用 MSI 和 Javascript 时遇到了很多问题。这可能是键盘和椅子之间存在的问题:-),但我认为 JavaScript 也存在一些真正的问题。尽量避免复杂的脚本使用。对于像检索属性这样的简单事情,它们似乎对我来说工作正常。然而,该领域的专家对脚本自定义操作却是无情的:不要使用 vbscript/jscript 来编写自定义操作!(亚伦·斯特布纳),VBScript(和 Jscript)MSI CustomActions 很糟糕(Rob Mensching - WiX 仁慈)。
-
我还要补充一点,自定义操作的复杂性是“愚蠢,阴谋复杂“处理这些事情并不有趣。它会咬你。陷阱。你会在适当的时候发现你所犯的所有错误——当你继续前进时(然后你需要做一些解释)——它们通常不会是立即显而易见(升级、修补、卸载时突然出现问题,您的自定义操作在修复过程中运行错误,因为它没有正确调节并清除了某些注册表设置,静默安装无法正常工作 - 它使安装不完整,因为自定义操作仅存在于用户界面序列中,Windows XP 上存在您从未测试过自定义操作代码的运行时错误,目标系统上存在您未屏蔽的损坏内容,有人打电话给您并告诉您您的软件包没有无法与活动目录一起使用,您的软件包无法发布广告,它在所有韩国和日本系统上都会失败,自我修复会触发运行时警告并拒绝普通用户的访问,等等...)。您将没有时间修复一旦它击中你,你就可能不得不继续使用不合标准的解决方案来让自己领先于下一个障碍。不,我自己并没有经历过这一切。事实上,我在修复用于企业部署的第三方供应商 MSI 文件时发现了大部分问题。当您查看、比较、审查数百个软件包并将其调整为大规模部署的企业标准时,您确实会发现很多潜在的错误源。老实说,除了最简单的软件包之外,所有软件包都存在严重的缺点和错误。显然,您会看到几年前进行此类供应商设置时做错了什么。猜猜排名第一的是什么?当内置构造可用时过度使用自定义操作。
-
除此之外,部署固有的复杂性及其要求在任何机器、任何地方、任何状态下工作,还存在以下问题:MSI 技术边缘反模式。 MSI 技术的某些部分由于人们对其知之甚少,并且有时在实际使用中很脆弱而导致重复部署问题。这个答案中有一个简短的总结(向底部):如何更好地利用 MSI 文件(以及一个列表MSI 非常重要的企业利益 - and 现实世界包中常见技术问题的随机转储)。特别是后一个链接在我写完之后让我觉得不太理想。接受它的本质:混乱的、现实世界的建议,没有太多其他的东西。它发现了太多的问题,却没有在某些地方显示出太多的修复措施。
-
软件的很大一部分支持电话往往来自部署过程中发现的问题。正如故事所说:“...未能正确安装您的优秀软件可能会导致失败最昂贵的错误从事软件开发。你永远不可能希望出售一个无法测试的软件“(来自上面链接的答案之一)。此类问题的背后往往是不良的自定义操作。
-
我认为我们看到的最常见的不必要的自定义操作用途:
-
您通过自定义操作安装 Windows 服务。使用内置构造在 MSI 本身中可以更好地完成此操作。
-
您可以通过自定义操作将 .NET 程序集安装到 GAC。 Windows Installer 本身完全支持这一点,无需一行(有风险的)代码。
-
您运行自定义 .NET 程序集安装程序类。这些将用于开发和测试only。他们应该never作为部署的一部分运行。相反,您的 MSI 应该使用内置构造来部署和注册您的程序集。
-
您可以通过自己的 MSI 中的自定义操作来运行先决条件设置和运行时安装程序。这应该完全不同地完成。您需要的是一个可以按顺序启动您的设置及其先决条件的引导程序。商业部署工具,例如高级安装程序 and 安装盾有这方面的功能,但是免费框架,例如WiX 通过其刻录功能提供支持,还有免费的 GUI 应用程序,例如DOTNet安装程序(未经我测试)具有这些功能。
-
在这种特殊情况下,请相信我的话:通过自定义操作运行嵌入式设置最终会失败- 通常相当立即。 MSI 在调度、模拟、事务、回滚和整体运行时架构方面过于复杂,无法实现这一点。根据设计,一次只能运行一个 MSI 事务,这使得事情变得非常复杂。过去,您可以将嵌入的 MSI 文件作为 MSI 中的一个概念来运行,但这已被弃用 - 它无法正常工作。您必须按顺序运行每个设置。正确的顺序。有引导程序/链式程序可用,允许您定义这样的安装顺序。这是一个描述其中一些问题的答案(不要让问题标题让您失望 - 它是关于引导程序/链式程序和其他部署注意事项):Wix - 如何在没有 UI 的情况下运行/安装应用程序.