为什么最好在WiX / MSI设置中限制使用自定义操作? [英] Why is it a good idea to limit the use of custom actions in my WiX / MSI setups?

查看:99
本文介绍了为什么最好在WiX / MSI设置中限制使用自定义操作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么在WiX / MSI设置中限制使用自定义操作是一个好主意?






部署是大多数开发的关键部分。请给这个内容一个机会。我坚信,可以通过在应用程序设计中进行很小的更改来显着提高软件质量,从而使部署更合理,更可靠-这就是答案的全部内容-软件开发。 p>




这是一种问答形式的问题,与答案变得太长了:如何避免WiX中常见的设计缺陷/ MSI部署解决方案?

解决方案


Core :由于以下原因而导致的复杂性,自定义操作从本质上来说很复杂:




  • 排序- 条件化- (运行时-以哪种安装模式运行: ,修复,修改,卸载等)和 假冒问题s (运行它的安全上下文)。

  • 这会导致整体 可调试性较差 -很难在所有排列中进行测试。



应用程序启动 :解决方案? 首选应用启动代码。您将获得熟悉的调试上下文,通常可以将代码保留在主应用程序源中-非常重要。问题与以下问题相同:设置中的许可(如果可以,请删除)。







简短的 Folksy版本



总体:应声明现代设置,而不要编码。 考虑SQL查询,而不是脚本。应用经过测试的逻辑,您只需调用它们即可完成工作。




  • 请避免自定义操作


    • 他们会用你的头拧紧(并谋杀你的少女形象)!

    • 严重的是:他们部署失败的第一原因。

    • 它们具有 阴谋复杂性的特点,一旦发生故障,事情往往会意外中断,而不会发出警告

    • 部署是一个过程-您将不得不处理 过去的过失 。部署中断后清理工作可能成为一场噩梦。每次迭代都会添加新的潜在错误源(我的修复程序失败,失败等等)。

    • 运行时要求用于托管代码脚本自定义操作非常容易出错(我认为特别是.NET)。设置-如果有的话-应该具有 最小依赖项-因为它用于直接安装依赖项,并且应在 任何机器上以 任何状态运行中的 任何语言

    • 除了使用内置的MSI构造或WiX自定义功能之外,自定义操作通常可以避免了对应用程序设计的微小更改,从而不再需要复杂的自定义操作(以下示例)。


  • 花费 WiX 查找并查看内置MSI功能和扩展的时间href = http://www.installshield.com rel = nofollow noreferrer> Installshield 高级安装程序(以及其他供应商工具)。


    • 这些扩展名由现有的最佳部署专家完成,并且在大多数情况下已经过数千人的测试(在内置MSI功能的情况下为数百万美元)。

    • 如何想象这与您自己的专有代码相匹配?如果现有的解决方案足够好(通常是这样),那么您的代码将完全增加风险,而毫无收获。现成的解决方案甚至支持回滚-一种众所周知的被忽略且难以实现的功能-设计实际上需要此功能。

    • 换句话说:何时您使用现有的解决方案,不仅要借用实施,而且还必须借用扩展时的 QA UAT 测试这可以节省数周的工作,并且为部署的稳定性做出巨大贡献

    • 所有需要做的就是花一些时间进行搜索和阅读依靠已有的资源,而不是用自己的代码来开始。哎呀,甚至您自己的经理也可以参与搜索……在梦想的世界中。

    • 通常不应编写代码,而应该声明设置!(认为SQL)。这就是Windows Installer的全部意义:声明要安装的内容,然后由安装程序引擎自己处理该序列。好处就是结果-正确完成。


  • 真的就是这样。继续阅读吧!在严肃的咆哮中这是巨龙。至关重要的是:从处理设置开发以及在企业环境中大规模部署此类设置中获得实际经验。常见问题变得更清楚-它们更容易识别。您可能会被真正要解决的问题所困扰-觉得自己永远无法预料到(进行公司包装和重新包装后,您会发现单个包装可能有多大问题-击败它们可能需要几天的时间有时会变成形状)。


    • 请记住,这并不像听起来那么糟糕:部署通常是一项低状态的技术尝试,而是高姿态的失败。错误确实显示

    • 在开发过程中进行调试很困难,但是对于部署而言,有时几乎是不可能的,因为您通常无法访问该问题。系统,每个问题系统都将处于完全不同的状态。

    • 老实说:未能将软件正确部署给最终用户可能是最昂贵的错误进行软件开发的人-没有人能看到您解决方案的强大之处-它会影响销售,支持,营销和进一步的解决方案开发。

    • 差劲的部署肯定可以下沉产品。不幸的是,良好的部署不足以保存产品







完善的Ranting版本:-)



如上所述本节与现有内容分开答案范围更广 如何避免WiX / MSI部署解决方案中常见的设计缺陷? (旨在帮助开发人员做出更好的部署决策的答案)。



6。 错误或不必要地使用了自定义操作



自定义操作的使用可能会导致大量部署问题,其中大多数都是非常严重的问题。 如果您的设置无法完成或崩溃,可以肯定地认为错误的自定义操作是错误的。



相应地,显而易见的解决方案是尽可能限制自定义操作的使用。自定义操作通常是 黑匣子(隐藏代码),而大多数MSI具有很大的透明度。可以轻松查看MSI格式( COM结构的存储文件),并且基本上可以从其MSI数据库文件中推断出MSI文件所做的一切-除了已编译的自定义操作(脚本自定义操作仍为白框-您可以看到是什么)



在这种适龄的恶意软件中,这些黑盒自定义操作(以提升的权限运行)可能不止一种皱眉。它们不仅是稳定性和可靠性问题,而且是全面的安全问题。



6.1自定义操作的过度使用




  • 赦免下面列出的琐事。其中很多可能是平庸的,但也许可以使用列出的参数为自己辩护,从而避免自定义操作并寻求更好的解决方案-通常涉及更智能的应用程序启动序列和应用程序自配置。相信我们,应用程序编码比处理Windows Installer复杂的自定义操作的条件,排序和模拟更有趣。

  • 以下内容已被更新很多次,以致于本节略有改动。到处都是重复的或重复的。将在时间允许的情况下进行清理。

  • 开发人员擅长编码-因此,在充分尊重的前提下-您倾向于过度使用自定义操作来做更好的事情使用内置MSI功能现成的MSI扩展解决方案(例如WiX中用于诸如 XML文件更新的高级功能)完成的操作, IIS COM + 防火墙规则驱动程序安装自定义权限注册表项,修改NT特权等...在商业工具(例如Installshield和Advanced Installer)中也可以找到这种支持。

  • 也可以这样做应用程序启动顺序的一部分,许多自定义操作完成了。主要示例是初始化用户数据并将设置文件复制到每个用户个人资料。这里有一些关于此问题的摘要:在当前用户配置文件中,从管理员配置文件中创建文件夹和文件。

  • 很明显,但是由于不了解已有内容,经常使用自定义操作通过现成的解决方案可以开箱即用。这一直在我们所有人身上发生,不是吗?总是有一些更聪明的方式来做事情,这些事情会为您省去很多麻烦?总的来说,尽管有时您正在开创新。除非您绝对需要,否则请不要在设置中开辟新天地!将其保存为您的应用程序。

  • 我想强调一下,这些内置的Windows Installer解决方案以及WiX和商业工具的扩展已经由可用的最佳部署专家编写。强>。而且,更重要的是,它们已被成千上万的人使用和测试-数十亿人使用内置的MSI功能。 您真的认为自己可以做得更好吗?故事的寓意:选择自己的战斗方式并运用出色的编码技能来解决新问题,并且让部署尽可能愚蠢 >。使用已有的东西,不要重蹈覆辙。部署中的未知因素太多,无法控制的变量太多-您正在 任何状态中处理 任何计算机 >任何语言 请参阅此处的部署复杂性部分 如果您想获取示例(在页面下方),仅简要介绍一下目标系统在您的程序包被击中时其状态可能会有所不同的所有方式。每个变量都是自定义代码的新陷阱-从 OS版本应用程序资源再到恶意软件情况列表不停。正如结论在链接内容中所读到的: 部署是一个简单的概念,其中包含可能导致最神秘错误的变量的复杂混合-包括开发人员最喜欢的错误:间歇性错误。我们都知道这类错误的严重性不能高估,因为它们通常无法正确调试。

  • 某些高级操作必须在您的设置中完成-因为它们需要高权限,并且您的应用程序在运行时不应请求此权限。这是用于高级,提升的系统配置的设置-接受这种复杂性,但是要使用现成的解决方案!不要滚动自己的脚本和解决方案,使用经过良好测试的内置东西。您的脚本会在韩国正确运行吗?您的自定义操作是否会受到主要的反恶意软件口径解决方案的阻碍,而您从来没有时间来测试脚本?您是否有时间编写自己的检查,以确定计算机上是否安装了某些必备的运行时-在所有语言环境和所有OS版本中都可以运行? 这里潜在的错误令人震惊-并且有时无法正确测试。您是否有阿拉伯文,中文,韩文或日文的测试机?也许你会。但是,您是否有要测试的终端服务器?韩国的终端服务器怎么样?您是否使用MSI广告测试了设置? 要使高级系统管理功能正常工作,必须使设置尽可能愚蠢和标准花几天时间寻找现成的解决方案,然后再自己写任何东西。请记住,使用现成的解决方案,您不仅要借用他们的代码,而且要借用他们创建者的质量保证,测试和UAT,这几乎是您永远都希望重复的。

  • Real-世界测试是唯一重要的标准-没有替代品。不要承受这个痛苦的世界!通过Windows Update部署的Windows中的微小变化以及您的自定义操作以多种方式中断。选择更好的战斗以利用您的技能。如果您进行了设计,则Windows安装程序将进行反击。

  • 部署过程中有很多事情使其变得复杂-而不像我们想要的那样愚蠢(只需复制一些织补文件),您的奋斗目标是使其尽可能简单,但不要再简单。以下是部署任务列表,显示了为什么很难使软件包足够笨:程序安装的好处和真正目的是什么?只要有可能,请仅使用现成的结构-这是第一个容易获得的结果。您需要做的就是阅读和搜索一些内容。

  • 最后,我将添加所有自定义操作都应支持回滚,以便将如果安装失败,系统将恢复到原始状态。在现实世界中,这几乎是从未执行过的即席自定义操作(以我的经验)。相信我处理起来很复杂-我担心回滚一词,因为在C ++中实现MSI回滚后,西伯利亚爱斯基摩人担心沐浴一词。这不是我有过的最有趣的事情,但是最终它可以正常工作。如果您希望您的设置没有太多的依赖关系,那么C ++是可行的方法,众所周知,处理起来并不容易。现成的解决方案支持开箱即用的回滚-仅需少量阅读和搜索就可以轻松实现。复杂性是的,但是您的立场更加坚定。至关重要的是:一旦在日本的计算机上发生了模糊的错误,我们便可以进行社区修复,或者需要第三方供应商对其进行排序。


  • 毕竟从纯粹的技术层面上讲,这些一般观察在Windows安装程序中的自定义操作在实施计划条件回滚,因此应在绝对必要时使用(通常用于早期采用者)。 运行时要求是进一步的复杂性-例如,对.NET运行时,PowerShell或Installscript运行时(Installshield的脚本语言-的特定版本)的特定版本的依赖关系,但它在很大程度上已解决了运行时的问题。 ,这曾经是一个问题。)


  • 缺少运行时要求引起的错误可能是一个巨大的难题-对于零获得。因此,在进行自定义操作时,我仅使用最小依赖C ++ dll Installscript 。碰巧我使用 VBScript JavaScript 来执行用户界面序列中的只读自定义操作。这些仅检索数据,而无需进行系统更改。这些是不容易出错的唯一类型的自定义操作。但是,应将它们设置为在不检查退出代码的情况下运行(以防止它们触发正在运行的安装程序中的回滚或中止-通常在主要升级模式下)。

  • 此外:Windows Installer主机拥有自己的脚本运行时引擎,因此,除非目标系统实际上已损坏(正常系统中不会缺少运行时),否则您可以运行活动脚本(VBScript,Javascript等)。这与托管代码自定义操作相反-目标系统目前完全没有.NET运行时是可能的(2018年1月)。现在,随着.NET成为Windows中真正的内置功能和必需功能(或Windows Installer本身托管的某些最低版本),这种情况将来会改变。托管的自定义操作代码由于种种原因而失败仍然存在问题-例如使用错误的.NET版本来运行它,或加载的CLR版本错误以及被使用等...我在这里的经验有限,但是我认为问题很严重。不过,最终,我们都会编写我认为的托管代码自定义操作。不过,我仍然会在全球范围内使用C ++。

  • Powershell脚本对于自定义操作特别有毛病,因为它们显然用完了进程并且无法访问MSI的会话对象(来源:MSI专家Chris Painter)。 Powershell还要求安装.NET框架。 我永远不会将Powershell脚本用于自定义操作-甚至不用于内部公司部署。您的来电。就像一个样本一样,以下是该领域的专家,他发表了自己的见解(年龄较大的博客文章,但如果您问我仍然很重要):不要使用托管代码来编写您的自定义操作!

  • 我尝试编写不同自定义操作类型的优缺点摘要。坦白说,我对此不太满意,但是在这里是: Windows Installer在Win 10上失败,但在使用WIX的Win 7上失败。我不满意吗?对JavaScript的建议是一件事-我很少使用它,尽管它比VBScript更好的语言-特别是对于错误处理-我在将Javascript与MSI结合使用时遇到了很多问题。可能是键盘和椅子之间存在问题的一种情况:-),但我认为JavaScript也有一些问题。尝试避免复杂地使用脚本。对于简单的事情,例如检索属性,它们似乎对我来说工作正常。但是,该领域的专家对脚本自定义操作毫不留情:不要使用vbscript / jscript编写您的自定义操作!(Aaron Stebner), VBScript(和Jscript)MSI CustomActions很烂(Rob Mensching-WiX慈善)。

  • 让我补充一点,自定义操作的复杂性是 愚蠢的,阴谋的复杂性,而不是有趣的东西。咬你陷阱您会在适当的时候发现自己犯的所有错误-继续前进(然后需要做一些解释)-这些错误通常不会立即显而易见(升级,修补,卸载,运行自定义操作时突然出现问题)在修复过程中错误地进行了调试,因为它的安装条件不正确,并且擦除了某些注册表设置,静默安装无法正常工作-由于自定义操作仅存在于用户界面序列中,因此安装不完整,您在Windows XP上存在运行时错误从未使用您的自定义操作代码进行测试,目标系统上有损坏的东西,您没有躲开自己,有人打电话给您,并告诉您您的程序包不适用于活动目录,您的程序包无法发布,失败在所有韩语和日语系统上,自我修复都会触发运行时警告,普通用户无法访问,等等。一旦遇到问题,您将没有时间正确解决此问题,并且您可能将不得不采用次标准的解决方案,以使自己在下一个障碍中领先。不,我自己没有经历过所有这些。实际上,在为公司部署修复第三方供应商MSI文件时,我发现了大多数这些问题。当您查看,比较,查看数百个软件包并将其适应企业标准以进行大规模部署时,您会发现很多潜在的错误源。老实说,除了最简单的软件包以外,所有软件包都存在严重的缺陷和错误。显然,几年前进行此类供应商设置时,您会发现自己做错了什么。 您猜猜什么是最重要的?当内置构造可用时,过度使用自定义操作。

  • 此外,部署的内在复杂性及其要求可在任何机器上,在任何状态下,都存在 MSI技术边界反模式的问题。 MSI技术的某些部分会导致重复部署问题,因为人们对其了解不多,有时在实际使用中也很脆弱。在此答案中有一个简短的摘要(朝底部):如何更好地利用MSI文件(以及 MSI的非常重要的公司利益-和随机转储现实软件包中常见的常见技术问题)。特别是在我写完后一个链接使我感到不理想。把它当作是什么:杂乱无章的,现实世界中的建议,没有太多其他建议。它可以识别太多问题,而又不会在地方显示很多补丁。

  • 软件支持电话的很大一部分往往来自于部署期间出现的问题。过程。随着故事的发展: ...未能正确安装您的优质软件,这可能是软件开发中发生的最昂贵的错误。您永远都希望出售一款能够永远无法测试(来自上述链接的答案之一)。错误的自定义操作通常是导致此类问题的原因。


  • 我认为最常见的不必要的自定义操作用途是




    • 您可以通过自定义操作安装Windows服务


    • 您可以通过自定义操作将.NET程序集安装到GAC。

    • 强>。 Windows Installer本身完全支持此功能,而无需一行(风险)代码。


    • 您运行自定义.NET程序集安装程序类 。这些仅用于 的开发和测试。它们不应从不作为部署的一部分运行。相反,您的MSI应该使用内置结构来部署和注册程序集。


    • 您可以通过自定义操作来运行必备安装程序和运行时安装程序自己的MSI 。这应该完全不同地完成。您需要的是一个引导程序,可以按顺序启动设置及其先决条件。商业部署工具,例如高级安装程序 Installshield 具有此功能,但免费框架如 WiX通过其刻录功能提供支持,并且还有免费的GUI应用程序,例如 DOTNetInstaller (由我试用)具有这些功能。


    • 在这种特殊情况下,请您相信:通过自定义运行嵌入式设置行动最终会失败-通常会立即失败。 MSI的调度,模拟,事务,回滚和整体运行时体系结构过于复杂,因此无法实现。根据设计,一次只能运行一个MSI事务,这使事情变得非常复杂。过去,您可以将嵌入式MSI文件作为MSI中的一个概念来运行,但已弃用-它无法正常运行。您必须按顺序运行每个设置。正确的顺序。有 bootstrappers / chainers (引导程序/链接程序)可用,可以用来定义这种安装顺序。这是描述其中一些问题的答案(不要让问题标题让您失望-它与引导程序/链接程序和其他部署注意事项有关): Wix-如何在没有UI的情况下运行/安装应用程序





6.2自定义操作备选方案




  • 在WiX和其他工具(如Installshield和Advanced Installer)中找到的现成解决方案已经过尝试和测试,并且至关重要地还实现了适当的回滚支持-自定义操作几乎总是缺少此功能实施-甚至在其他良好的供应商MSI设置中也是如此。回滚是一项非常重要的MSI功能。在各种环境中积极使用和测试,您无法与大型用户社区提供的质量竞争。充分利用这些功能。


  • 除了使用内置的MSI构造或WiX自定义功能之外,自定义操作通常可以通过对以下内容进行较小的更改来避免应用程序设计,以便不再需要复杂的自定义操作。我看到许可作为部署方式的示例简化以提高可靠性。




    • 这是非常重要的一点,经常被忽略。有时,一些高质量的小时或几天的编码以及一些高质量的UAT / QA时间可以防止长期存在的部署问题。没有足够的支持时间可以解决您可能会遇到的最糟糕的部署问题。


    • 此答案提供了关于部署总体复杂性的信息。 >: Windows Installer和WiX的创建(朝向底部)。部署是一个复杂的交付过程,它面临几个严峻的挑战: 1)部署错误的累积性质 2)正确调试的难度 3)影响全球目标计算机的几乎无限范围的外部因素和变量-结论是,必须使部署尽可能简单以确保可靠性。有很多干预因素使您不喜欢开发人员:间歇性错误。建议使用上面的链接来获得更充实的解释。





6.3高级自定义操作问题(超出运行时故障)




  • 一个非常常见的自定义操作问题是其错误的计划和尝试修改系统从非提升立即模式操作开始。 这些是高级的MSI设计缺陷,对于看到其他方法可以正常工作的用户来说,这些缺陷无法立即识别。


  • 绝对不要在MSI的InstallExecuteSequence中的InstallFinalize之后插入立即模式自定义操作,以尝试修改系统(读/写)。如果您的设置是通过SCCM之类的部署系统以静默方式部署的,这些操作将永远不会执行(再次,我上次检查)。


  • 从不尝试使用通过设置GUI激活的即时模式自定义操作来更改系统。这似乎对管理员用户有效,但是即时模式自定义操作不会提升,因此普通用户将无法正确运行它们。此外,当安装程序以静默方式运行时,从MSI GUI对系统所做的任何更改将永远不会完成(然后将跳过整个GUI序列)。 This is a very serious MSI design flaw: installing silently and interactively causes different results. This issue is mentioned in section 10 on silent install as well in this answer: How do I avoid common design flaws in my WiX / MSI deployment solution?. Silent install is a crucial feature for corporate deployment of your software. In corporations with control of their deployment, ALL deployment is done silently. Your setup GUI is simply never seen. There are only a few exceptions I can think of, such as certain server deployments that may be done interactively, but all desktop and client software is deployed silently. Not supporting silent install properly is hence a horrendous deficiency and design flaw of your MSI setup. Please heed this advice. It is crucial for corporate acceptance of your software - I have recommended certain software to be thrown out from the standard system because its deployment is so dangerous for the system that we just don’t want to deal with it. Virtualization and sandboxing (APP-V - virtual packages - or full on virtual machines) are big today precisely because of these issues (misbehaving applications and setups).


  • All custom actions that make changes to the system must be inserted in the \"transacted section\" of the installation sequence. This Windows Installer Transaction (think database transaction commit) runs between the standard actions InstallInitialize and InstallFinalize in the InstallExecuteSequence and runs with elevated rights. All changes to the system are to take place in this transaction - anything else is erroneous (but unfortunately quite common). All custom actions inserted here should have a corresponding rollback custom action implemented as well, and this should undo any changes done to the system in case the install fails and gets rolled back.



Why is it a good idea to limit the use of custom actions in my WiX / MSI setups?


Deployment is a crucial part of most development. Please give this content a chance. It is my firm belief that software quality can be dramatically improved by small changes in application design to make deployment more logical and more reliable - that is what this "answer" is all about - software development.


This is a Q/A-style question split from an answer that became too long: How do I avoid common design flaws in my WiX / MSI deployment solution?.

解决方案

Core: Essentially custom actions are complex to get right because of complexity arising from:

  • Sequencing-, Conditioning- (when it runs - in what installation mode: install, repair, modify, uninstall, etc...) and Impersonation-issues (security context it runs in).
  • It results in overall poor debugability - very hard hard work to test in all permutations.

Application Launch: Solution? Prefer application launch code. You get a familiar debugging context and can usually keep the code in the main application source - very important. The issue is the same for: licensing in setups (take it out if you can).


Short "Folksy" Version:

Overall: a modern setup should be "declared", not coded. "think SQL queries, not scripting". Apply well-tested logic that you just invoke to do the work. More on that later.

  • Avoid custom actions if you can.
    • They will screw with your head (and do murder to your girly figure)!
    • Seriously: they are the number one cause of deployment failure.
    • They feature a "conspiratory complexity" whereby things often break unexpectedly and without warning after you have deployed your setup for some time and it is "in the wild".
    • Deployment is a process - you will have to deal with "past sins" for every new release. It can become a real nightmare to clean things up after broken deployments. Each iteration adds new, potential error sources (my fix for my failed fix, failed, etc...).
    • Runtime requirements for managed code and scripting custom actions are very error prone (.NET in particular in my opinion). A setup - if anything - should feature "minimum dependencies" - since it is used to install dependencies outright and should run on "any machine" in "any state" in "any language".
    • Apart from using built-in MSI constructs or WiX custom features, custom actions can often be avoided by minor changes to the application design so that complex custom actions are no longer needed (samples below).
  • Spend the time to find and review built-in MSI features and extensions from WiX, Installshield, Advanced Installer (and other vendor tools).
    • These extensions are made by the best deployment experts available, and have in most cases been tested by thousands of people (millions and billions in the case of built-in MSI features).
    • How can you conceivably match this with your own proprietary code? If the existing solution is good enough - which it normally is - then your own code is entirely added risk for no gain whatsoever. The ready-made solutions even support rollback - a notoriously neglected and hard-to-implement feature - that is actually required by design.
    • In other words: when you use the existing solutions, you borrow not just the implementation, but crucially also the QA, UAT and testing of the extensions when you use them. This can save weeks of work and contribute greatly to deployment stability.
    • All that is needed is to spend some time searching and reading up on what is already available, rather than jump-starting things with your own code. Heck, even your own manager could get involved searching... In a dream world.
    • A setup should generally not be coded, it should be declared! (think SQL). This is what Windows Installer is all about: you declare what to be installed, and the sequence is taken care of by the installer engine itself. Benefits result - when done right.
  • That's about it really. Read on if you dare! Here be dragons in the midst of serious ranting. And crucially: real-life experience from dealing with both setup development, and also large scale deployment of such setups in corporate environments. Common problems become clearer - they are more identifiable. And you may get burned with problems you really have to answer for - that you feel you could never have foreseen (doing corporate packaging and repackaging you get to see just how much can be wrong with a single package - it can take days to beat them into shape at times).
    • Please remember, and this is not meant as bad as it sounds: deployment is generally a low status technology endeavor, but a high profile failure. Errors really show. And someone will get to answer for it, and support will really feel it.
    • Debugging during development is hard, but for deployment it is sometimes nearly impossible since you generally have no access to the problem systems, and each problem system will be in a totally different state.
    • In all honesty: failing to get software deployed correctly to end users may be close to being the most expensive error to make in software development - nobody can witness the greatness of your solution - and it affects sales, support, marketing and further solution development.
    • Poor deployment can definitely sink a product. Unfortunately good deployment isn't enough to save a product.

Fleshed Out Ranting Version :-)

As stated above this section was split from an existing answer with broader scope: How do I avoid common design flaws in my WiX / MSI deployment solution? (an answer intended to help developers make better deployment decisions).

6. Erroneous or unnecessary use of custom actions.

A plethora of deployment problems can be caused by custom action use - most of them very serious. If your setup fails to complete or crashes, it is a fair bet that a erroneous custom action is at fault.

Accordingly the obvious solution is to limit your use of custom actions whenever possible. Custom actions are (often) "black box" (hidden code) whereas most of MSI features a lot of transparency. The MSI format can be viewed easily (COM-structured storage file), and everything that an MSI file does can essentially be deduced from its MSI database file - with the exception of compiled custom actions (script custom actions are still white box - you can see what is going on, unless they are obfuscated).

In this age of malware, these black box custom actions - that run with elevated rights - may become frowned upon in more ways than one. They are not just stability and reliability issues, but a full-blown security issue.

6.1 The Overuse of Custom Actions

  • Pardon the "trifles" listed below. A lot of this may be banality, but maybe use the arguments listed to make a case for yourself to avoid custom actions and to work on better solutions - usually involving smarter application launch sequence and application self-configuration. Trust us, application coding will be more interesting than dealing with Windows's Installer's complex conditioning, sequencing and impersonation for custom actions.
  • The below has been updated so many times that sections are a little bit out of sequence or repetitive here and there. Will be cleaned up as time allows.
  • Developers are good at coding - so with all due respect - you tend to overuse custom actions to do things that are better done using built-in MSI features or ready-made MSI extension solutions such as those available in WiX for advanced things such as XML file updates, IIS, COM+, firewall rules, driver installation, custom permissioning for disk and registry entries, modify NT privileges, etc... Such support is also found in commercial tools such as Installshield and Advanced Installer.
  • It is also possible to do a lot of what is done in custom action as part of an application's launch sequence. The prime example is initializing user data and copying settings file to each user profile. There is a little summary of this issue here: Create folder and file on Current user profile, from Admin Profile.
  • It is obvious, but very often custom actions are used out of ignorance of what is already available "out of the box" by means of ready-made solutions. This happens to all of us all the time, doesn't it? There is always some smarter way to do things that would have saved you lots of grief? In general anyway - though sometimes you are breaking new ground. Don't break new ground in your setup - unless you absolutely have to! Save it for your application.
  • I want to emphasize that these built-in Windows Installer solutions and extensions from WiX and commercial tools have been written by the best deployment specialists available. And moreover, and even more importantly, they have been used and tested by thousands, millions - heck even billions of people for built-in MSI features. Do you really think you can do any better? Moral of the story: pick your battles and use your great coding skills to solve new problems, and let deployment be as dumb as possible. Use what already works, and don't reinvent the wheel. There are too many unknowns in deployment, too many variables that can't be controlled - you are dealing with "any machine" in "any state" and in "any language". See the Complexity of Deployment section here if you want examples - a bit down the page - just a short dump of all the ways your target systems may differ in their states when your package hits it. Each variable is a new bear trap for custom code - from OS version, to application estate to malware situation. The list goes on and on. As the conclusion reads in the linked content: "Deployment is a simple concept, with a complicated mix of variables that can cause the most mysterious errors - including the developer favorite: the intermittent bug. As we all know the seriousness of such bugs can not be overstated as they are often impossible to debug properly."
  • Certain advanced things must be done in your setup - since they require elevated rights and your application should not request this whilst running. This is what a setup is for, advanced, elevated system configuration - so embrace this complexity, but use ready made solutions! Don't roll your own script and solutions, use built-in, well tested stuff. Will your script run correctly in Korea? Will your custom action be blocked by a major anti-malware solution of caliber that you never had the time to test your script with? Do you have time to write your own check for whether a certain prerequisite runtime is installed on the computer - which works in all locales and across all OS versions? The potential for bugs here is staggering - and sometimes impossible to test properly. Do you have test machines in Arabic, Chinese, Korean or Japanese? Maybe you do. But do you have a terminal server to test on? How about a Korean terminal server? Did you test your setup with MSI advertisement? For advanced system management features to work, you have to make your setup as dumb and standard as possible. Spend several days looking for ready-made solutions before you write anything on your own I'd say. Remember, with ready-made solutions you are not just borrowing their code, but crucially their creator's QA, testing and UAT - which you can almost never hope to repeat.
  • Real-world testing is the only yardstick that matters - there is no substitute. Don't take on this world of pain! A slight change in Windows deployed via a Windows Update and your custom action breaks in any number of ways. Choose a better battle to make use of your skills. If you fight the design, then Windows installer fights back.
  • And there is a lot going on with deployment that makes it complex - and not dumb like we want it (just copy some darn files), your fight is to make it as simple as possible, but no simpler. Here is a list of deployment tasks showing why it is hard to get your package "dumb enough": What is the benefit and real purpose of program installation? Use only ready-made constructs whenever you can - it is the first easy win. All you need to do is to read and search a little.
  • Finally I will add that all custom actions are supposed to support rollback to put the system back to the original state if the install fails. In the real-world this is almost never done in an ad-hoc custom action (in my experience). Believe me it is complicated to deal with - I fear the word "rollback" as a Siberian husky fears the word "bath" after I implemented MSI rollback in C++. Not the most fun I ever had, but it eventually worked properly. If you want your setup to be without too many dependencies, C++ is the way to go, and as we all know it is not trivial to deal with. The ready-made solutions support rollback out of the box - it is an easy-win for only a bit of reading and searching to enable them. Complexity yes, but you are on more solid ground. And crucially: once an obscure error happens on a Japanese machine we can work for a community fix, or a third party vendor needs to sort it.

  • After all those "general observations", on a purely technical level, custom actions in Windows Installer are very complex with regards to implementation, scheduling, conditioning and rollback, and should hence be used when absolutely necessary (often for early-adopter stuff). A further complexity is runtime requirements - for example dependencies on specific versions of the .NET runtime, or PowerShell, or Installscript runtimes (scripting language of Installshield - it had a runtime dependency, but this is largely solved now, it used to be a problem).

  • Errors from missing runtime requirements can be a enormous hairball to deal with - for zero gain. For this reason I only use minimal dependency C++ dll's or Installscript when making custom actions. It happens that I use VBScript or JavaScript for read-only custom actions in the user interface sequence. These just retrieve data, and make no system changes. These are the only types of custom actions that are not that error prone. They should however be set to run without checking exit codes (to prevent them from triggering rollback or abort in a setup that is being run - often in major upgrade mode).
  • Also: Windows Installer hosts its own scripting runtime engine, so you know your active scripts (VBScript, Javascript, etc...) can run unless your target system is actually broken (there is no missing runtime on a normal system). This is in contrast to managed code custom actions - it is entirely possible for target systems to have no .NET runtime at this point (Jan 2018). Now this will change in the future, as .NET becomes a really built-in and required feature in Windows (or some minimal version of it hosted by Windows Installer itself). There are still problems with managed custom action code failing for strange reasons - such as the wrong .NET version being used to run it, or the wrong version of the CLR being loaded and being used, etc... I have limited experience here, but the problems are serious in my opinion. Eventually, though, we will all write managed code custom actions I think. I would still use C++ for worldwide distribution scenarios though.
  • Powershell scripts are particularly hairy for custom actions as they apparently run out of process and can't access the MSI's session object (source: MSI expert Chris Painter). Powershell also requires the .NET framework to be installed. I would never use Powershell script for custom actions - not even for internal, corporate deployment. Your call. Just as a "sample", here is an expert in the field stating his opinion (aging blog item, but still relevant if you ask me): Don’t use managed code to write your custom actions!
  • I tried to write a summary of pros and cons of different custom action types. Frankly I am not too happy with it, but here it is: Windows Installer fails on Win 10 but not Win 7 using WIX. What I am not happy with? The recommendation of JavaScript for one thing - I have used it seldomly, and although it is a better language than VBScript - particularly for error handling - I have had lots of problems using Javascript with MSI. It may be a case of the problem existing between the keyboard and the chair :-), but I think there are some real gotchas with JavaScript as well. Try to avoid complex use of scripts. For simple things like retrieving properties they seem to work OK for me. However, the experts in the field are merciless on script custom actions: Don’t use vbscript/jscript to write your custom actions! (Aaron Stebner), VBScript (and Jscript) MSI CustomActions suck (Rob Mensching - WiX benevolency).
  • Let me also add that custom action complexity is "silly, conspiratory complexity" not fun-to-deal-with stuff. It bites you. Gotchas. You will discover all the mistakes you have made in due course - as you move along (and then you have some explaining to do) - they will often not be immediately obvious (problems suddenly arise when upgrading, patching, uninstalling, your custom action runs erroneously during repair because it is not conditioned properly and wipes out certain registry settings, silent install doesn't work properly - it leaves the install incomplete because the custom action only exists in the user interface sequence, there are runtime errors on Windows XP that you never tested your custom action code with, there are broken things on target systems that you didn't shield yourself from, someone calls you and tells you your package doesn't work with active directory, your package can't be advertised, it fails on all Korean and Japanese systems, self-repair triggers runtime warnings and access denied for normal users, etc...). You will have no time to fix this properly once it hits you, and you will likely have to proceed with sub-standard solutions to get yourself ahead over the next hurdle. And no, I didn't experience all of this myself. In fact I discovered most of these problems when fixing up third party vendor MSI files for corporate deployment. You really discover a lot of potential error sources when you see, compare, review and adapt hundreds of packages to a corporate standard for large scale deployment. In all honesty there are serious shortcomings and errors in all but the simplest of packages. And obviously you get to see what you did wrongly when you made such vendor setups a few years earlier. And guess what tops the list? Overuse of custom actions when built-in constructs were available.
  • And to add to it all, the inherent complexity of deployment with its requirement to work on any machine, anywhere in any state, there is the issue of MSI technology borderline anti-patterns. Parts of the MSI technology that are causing repeated deployment problems because they are poorly understood, and sometimes fragile in real-world use. There is a brief summary of this in this answer (towards the bottom): How to make better use of MSI files (along with a list of the very important corporate benefits of MSI - and a random dump of common technical problems seen in real-world packages). Particularly the latter link has struck me as less than ideal after I wrote it. Take it for what it is: messy, real-world advice without much else going for it. It identifies too many problems without showing much in the line of fixes in places.
  • A substantial proportion of a software's support calls tend to come from problems seen during the deployment process. As the story goes: "...failing to properly install your great software may be close to being the most expensive error to make in software development. You can never hope to sell a software that was never possible to test" (from one of the linked answers above). A bad custom action is very often behind such problems.

  • The most common unnecessary custom action uses we see are in my opinion:

    • You install Windows Services via custom actions. This is much better done in the MSI itself using built-in constructs.

    • You install .NET assemblies to the GAC via a custom action. This is fully supported by Windows Installer itself without a line of (risky) code.

    • You run custom .NET assembly installer classes. These are to be used for development and testing only. They should never be run as part of deployment. Rather your MSI should use built-in constructs to deploy and register your assembly.

    • You run prerequisite setups and runtime installers via a custom action in your own MSI. This should be done entirely differently. What you need is a bootstrapper that can launch your setup and its prerequisites in a sequence. Commercial deployment tools such as Advanced Installer and Installshield have features for this, but free frameworks such as WiX has support via its Burn feature, and there are also free GUI applications such as DOTNetInstaller (untested by me) with these kind of features.

    • Please take my word for it in this particular case: running embedded setups via a custom action will fail eventually - usually rather immediately. MSI is too complicated in its scheduling, impersonation, transaction, rollback and overall runtime architecture to make this possible. Only one MSI transaction can run at a time by design, and this makes things very complicated. It used to be you could run embedded MSI files as a concept in MSI, but this was deprecated - it didn't work properly. You must run each setup in sequence. The correct sequence. There are bootstrappers / chainers available that will allow you to define such an installation sequence. Here is an answer which describes some of them (don't let the question title throw you off - it is about bootstrappers / chainers and other deployment considerations): Wix - How to run/install application without UI.

6.2 Custom Action Alternatives

  • The ready-made solutions found in WiX and other tools such as Installshield and Advanced Installer, are tried and tested, and crucially also implement proper rollback support - a feature almost always missing from custom action implementations - even in otherwise good vendor MSI setups. Rollback is a very important MSI feature. You cannot compete with the quality delivered from a large user community with active use and testing in all kinds of environments. Make use of these features.

  • Apart from using built-in MSI constructs or WiX custom features, custom actions can often be avoided by minor changes to the application design so that complex custom actions are no longer needed. I see licensing as an example of how deployment can be simplified to improve reliability.

    • This is a very important point, and one that is very often ignored. Sometimes some quality hours or days of coding and some quality UAT / QA time can prevent long term deployment problems from ever existing. No amount of support time can solve the worst deployment problems you can create.

    • This answer provides a blurb about the overall complexity of deployment: Windows Installer and the creation of WiX (towards the bottom). Deployment is a complicated "delivery process" with several serious challenges: 1) the cumulative nature of deployment errors, 2) the difficulty of proper debugging, and 3) the virtually unlimited range of external factors and variables affecting target machines world-wide - the conclusion is that deployment must be made as simple as possible to be reliable. There are so many intervening factors leaving you with the developer favorite: the intermittent bug. The link above is recommended for a more fleshed out explanation.

6.3 Advanced Custom Action Problems (beyond runtime failures)

  • A very common custom action issue is their incorrect scheduling and attempting to modify the system from "non elevated" immediate mode actions. These are advanced MSI design flaws not immediately recognizable for people who see an otherwise working setup.

  • Never insert immediate mode custom actions after InstallFinalize in the InstallExecuteSequence of your MSI that attempt to modify the system (read/write). These actions will never run if your setup is deployed in silent mode via deployment systems such as SCCM (again, last time I checked).

  • Never try to change the system using immediate mode custom actions activated from the setup GUI. This will appear to work for admin users, but immediate mode custom actions are not elevated and hence regular users will not be able to run them without error. In addition any changes to the system done from the MSI GUI will never be done when the setup is run in silent mode (then the whole GUI sequence is skipped). This is a very serious MSI design flaw: installing silently and interactively causes different results. This issue is mentioned in section 10 on silent install as well in this answer: How do I avoid common design flaws in my WiX / MSI deployment solution?. Silent install is a crucial feature for corporate deployment of your software. In corporations with control of their deployment, ALL deployment is done silently. Your setup GUI is simply never seen. There are only a few exceptions I can think of, such as certain server deployments that may be done interactively, but all desktop and client software is deployed silently. Not supporting silent install properly is hence a horrendous deficiency and design flaw of your MSI setup. Please heed this advice. It is crucial for corporate acceptance of your software - I have recommended certain software to be thrown out from the standard system because its deployment is so dangerous for the system that we just don't want to deal with it. Virtualization and sandboxing (APP-V - virtual packages - or full on virtual machines) are big today precisely because of these issues (misbehaving applications and setups).

  • All custom actions that make changes to the system must be inserted in the "transacted section" of the installation sequence. This Windows Installer Transaction (think database transaction commit) runs between the standard actions InstallInitialize and InstallFinalize in the InstallExecuteSequence and runs with elevated rights. All changes to the system are to take place in this transaction - anything else is erroneous (but unfortunately quite common). All custom actions inserted here should have a corresponding rollback custom action implemented as well, and this should undo any changes done to the system in case the install fails and gets rolled back.

这篇关于为什么最好在WiX / MSI设置中限制使用自定义操作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆