Windows安装程序在Win 10上失败,但不是Win 7在使用WIX

我最近被分配到更新我们的项目安装程序在Windows 10上运行,我在如何让它工作有点损失。 我没有做安装程序的经验,并且正在不断熟悉我自己的stream程,以及我们的项目如何处理它。

到目前为止,安装程序可以正常运行在我们的Windows 7虚拟机上,但是在Windows 10虚拟机上运行时,安装程​​序会在最后失败,并开始回滚。 我已经得到它吐出一些日志文件,我正在挖掘他们,但是相当损失。

我追查了这一点:

MSI (s) (B0:F4) [17:39:02:883]: Note: 1: 1708 MSI (s) (B0:F4) [17:39:02:883]: Note: 1: 2205 2: 3: Error MSI (s) (B0:F4) [17:39:02:883]: Note: 1: 2228 2: 3: Error 4: SELECT `Message` FROM `Error` WHERE `Error` = 1708 MSI (s) (B0:F4) [17:39:02:883]: Note: 1: 2205 2: 3: Error MSI (s) (B0:F4) [17:39:02:883]: Note: 1: 2228 2: 3: Error 4: SELECT `Message` FROM `Error` WHERE `Error` = 1709 MSI (s) (B0:F4) [17:39:02:883]: Product: GPEP -- Installation failed. 

接近似乎在安装程序似乎失败时发生的结尾。

下一行有这个结尾:

 Installation success or error status: 1603. 

我已经看到了错误,并发现这个错误1603

我正在寻找该网页上的解决scheme,但所有这些都应该是有序的。 我们以相同的方式在Win 10和Win 7虚拟机上以相同的权限运行安装程序。

我怀疑这将有足够的信息得到任何具体的反应,所以我比任何东西我寻找build设性的意见如何看看,以及如何弄清楚。 我可以发布更多的细节,但是信息量如此之大,我不知道如何挑选真正相关的东西。

加上这个答案 – 这个评论太长了,我认为这也是正确的答案。 如果你阅读这个答案,也可以看看我上面提到的Rob Mensching (WiX的创建者)提供的一个很好的MSI日志文件调试技巧,以及如何通过启用“flush to log”来确保所有条目都进入日志文件崩溃的自定义操作。


答案

依赖像Powershell这样的缺失运行时肯定会触发回滚 。 MSI为某些脚本自定义操作( 活动脚本 )提供了自己的运行时。 例如VBScript和JavaScript。 为了可靠的部署,建议所有使用的自定义操作要么是自包含的最小依赖性C ++ dll或可执行文件(win32),要么是不太可取的VBScript或JavaScript(如果使用Installshield,甚至是Installscript – 请参阅下面的详细信息)。

用于可靠性和健壮性的最差自定义操作是需要特定版本的.NET框架的.NET二进制文件。 这也适用于PowerShell – 这不仅是托管代码,也是一个脚本 。 我很想说这些技术不应该用于部署,但是如果您需要使用PowerShell,您至少必须在安装开始时添加一个“验证PowerShell安装的”自定义操作,然后优雅地退出如果PowerShell不可用,则显示(和/或记录)适当的错误消息。

这是真正的答案的结束:-)。 下面是一些“详细的思考”,如果你正在做一个普遍分发的包(而不是你自己公司内部部署的包)。 如果我是你,即使只在内部进行部署,我也会阅读它, PowerShell自定义操作可能是一个酝酿中的口径部署问题

托管代码和脚本都是有问题的。 PowerShell同时有效。 Rob Mensching的博客是关于为什么脚本自定义操作不好的 。 从本质上讲:脚本是脆弱的,他们缺乏语言功能,他们很难调试,反病毒产品经常阻止他们。 阅读博客。 这里是关于为什么托管代码不好的Aaron Stebner的博客 。 从本质上讲,当你依赖.NET框架时,不能保证有一个适当的运行环境。


详细的情绪

我不确定在Win7和Win10上安装了哪些标准。 如果您正在为您的公司部署一个“内部软件包”,我认为只需添加一个可靠的PowerShell检查检查即可,如果找不到PowerShell,则可以通过一个有意义的错误消息中止。 但是整体.NET二进制文件和PowerShell脚本是可靠性最差的自定义操作。 我绝不会将它们用于针对不同计算机的设置。

如果您正在为任何位置的计算机进行常规分发 ,我会花时间将PowerShell脚本转换为其他内容。 最好是一个C ++的DLL – 我觉得最可靠。 没有依赖性可言或层依赖。 即使InstallScript也可以接受(如果你已经使用了Installshield的话)(它现在可以在没有预先安装的运行环境下运行,这大大提高了它的可靠性和实用性),尽管它的语法比较陈旧,被低估 – 它做的工作,比C ++简单)。

JavaScriptVBScript自定义操作甚至可以用于通常分发给任何计算机的MSI,但仍不推荐 。 我倾向于将它们仅用于“内部公司部署”包。 这些可以是标准化的 ,关键的是脚本对其他系统管理员和打包者是透明的 。 他们可以查看和检查安装过程中正在执行的操作。 这通常是可取的, 也是MSI公司部署的关键好处之一 ,但有时您需要编译的二进制文件来隐藏实现细节 (例如,验证许可证密钥时)。 那么任何一种脚本都不能使用 – 显然。 通过透明化并嵌入到MSI(所以运行源总是可用的),它有助于不同的应用程序打包者在需要时能够拾取别人的工作。 而在一个部署团队中,总有人可以调试脚本 – 但很少人可能知道正确的C ++。 在内部应用程序的开发者没有太多部署知识的情况下制作他们自己的MSI文件的企业中,脚本可以完全误入歧途,并导致非常困难的部署问题。 经常需要的是对应用程序本身的小改动,以实现更可靠的部署。 例如,应用程序应该执行自己的启动配置 – 这些都不应该在安装脚本中完成,但许多开发人员都这样做。

使用脚本自定义操作是有争议的。 如果你问2个开发专家,你会得到4个意见。 在我看来,“白盒子”的自定义操作(脚本)对于企业用途是有利的,如果他们做了一些不常见的事情,那么人们就可以看到发生了什么事情。 对于一直需要的东西,公司应该在MSI文件中创建一个由定制表驱动的C ++ dll,它具有完整的QA和回滚支持 – 对于所有脚本自定义操作而言通常总是缺少一些东西(这并不是微不足道的实行)。 “数据驱动”(自定义表格)C ++自定义动作具有最小的依赖关系作为其最大的优势,而且它也是透明的(将会发生透明,但实际的实现被编译和隐藏 – 这也可以提高安全性)。 WiX工具包提供了这样一个自定义操作dll,用C ++编写的回滚支持。 它应该解决企业部署所需的大多数自定义任务。 所有这些都超出了你的问题 – 只是一个题外话:-)。


如果我猜测我会说Windows安装程序可能会更新为能够托管自己的运行时为Powershell – 但这只是猜测。 我不确定的技术细节 – 看起来整个.NET运行时将需要? 如果你问我,我仍然更喜欢JavaScript到PowerShell脚本 ,但是我意识到你可能会将PowerShell作为公司的标准吗? 此外, 总是比JavaScript脚本更喜欢JavaScript,因为它具有看起来像异常处理(VB脚本完全没有)的东西。

Rob MenschingChris PainterPhil WilsonBob Arnson和其他人(我不确定Stefan Kruger在脚本上立场,还是Robert Dickau的观点) – 会为此而杀了我,但是这是一个JavaScript自定义操作的模板未经测试,但看起来确定): 如何调试在Javascript中实现的MSI自定义操作? 。 如果我可以脱口而出:现在什么都比PowerShell更好 – 甚至是JavaScript。

放心,我浪费了很多时间调试极其糟糕的VB脚本自定义操作。 可能是曾经用于部署的最无能和被剥夺的语言。 On Error Resume Next错误处理? 它不会变得更糟。 我通常只使用脚本进行只读操作并设置属性操作

也许我们会在适当的时候看到VB Script被弃用,PowerShell作为一个可行的MSI脚本选项被添加了吗? 我不会认为这是安全的,直到所有正在使用的操作系统都至少安装了.NET框架的基准版本 – 即便如此,我相信策略可能会锁定特定版本的.NET。 你是否想要一个突然无法卸载的软件包,因为.NET框架的目标版本不再可用? 解决这样一个问题可能是一个令人难以置信的工作量 – 尤其是对于一个大包装庄园的公司。


推荐的自定义操作实现

我为自定义操作实现撰写了“建议”摘要。 它成了很长的一页,没有说太多 – 我删除了它。 相反,以下是我的自定义操作实施偏好的列表(按照稳健性和可靠性的下降顺序):

  1. C ++的DLL
  2. Installscript (仅限InstallShield)
  3. JavaScript的
  4. VB脚本
  5. C#DTF
  6. 电源外壳

概要:

  • 对我来说, PowerShell绝对是最糟糕的选择。 它是托管代码(不可靠的运行时) 脚本自定义操作(糟糕的调试)。
  • 我想编写C#/ DTF自定义操作,就像Chris所做的那样简单,但我不相信时机已经成熟 – 运行时环境无法得到保证。 在现实世界中,你不会抛弃一个工作的C ++ DLL而转而使用C#DLL。 这是一个巨大的可靠性降级。
  • C ++ dllInstallscript制定针对不同计算机的专业供应商设置的唯一选择 (在管理环境中不是标准化的桌面 – 公司,而是在世界上任何地方,处于各种不同状态,不同语言和不同硬件和软件配置的计算机) 。
  • 一个C ++自定义操作DLL比其他自定义操作的导出,构建设置和输出更难以设置和配置,但这不是不可能的。 作为回报,您会得到很多: 完整的调试功能高级语言功能错误处理最大的依赖关系 (确保启用静态链接以消除所有可能的依赖关系)。 对于调试,您可以简单地将Visual Studio调试器附加到自定义操作显示的消息框中,然后您可以单步执行代码。 这适用于用户和系统上下文自定义操作。 完全控制。 这实际上使调试C + +自定义操作比脚本自定义操作更容易,当然更可靠。
  • VB脚本我永远不会用任何东西了。 它没有错误处理使得它非常不可靠。 它只是不完整的语言。 我仍然认为它比托管代码更可靠。
  • 在托管环境中,“ 内部公司使用 ”可接受JavaScript 。 我永远不会使用它的供应商设置进行一般分配。 但是要在企业网络上分发包,可以使用它。 无论是开发人员打包自己的应用程序,还是应用程序打包者调整企业部署的第三方设置。 JavaScript操作的主要优点和缺点:
    • 如上所述,脚本只能在极少数情况下使用,并且win32 C ++ dll或者WiX的自定义动作dll应该用于所有人们倾向于重复使用的常见脚本任务。 只有在需要完成工作时才能使用脚本。
    • JavaScript自定义操作与所有脚本自定义操作一样,通常很难调试容易受到防病毒干扰,并且缺乏实现高级编码结构所需的语言功能 。 你只是没有C ++语言特性和灵活性
    • 脚本对于每个人都是透明的(包括目的和实现),并且可以由几个团队成员轻松地进行调试和维护,并在他们之间交换工作。 所有人都可以看到发生了什么事,每个人都可以快速地找到别人的工作。
    • 嵌入在MSI 的源代码正确的源代码,您不需要在存储库中分别维护源文件,以便像托管代码(C#)那样对其进行编译。 对于应用程序打包源代码管理很少设置是我的经验(应该是)。
    • 企业套餐的目标是标准的运营环境 (SOE)。 所有的工作站都是相同或相同的,具有相同的防病毒解决方案。 这显然意味着目标计算机比正常状态更加统一。 任何防病毒问题将被检测到,并可以进行管理。 就个人而言,我还没有看到这种软件包部署的简单脚本有任何主要的反病毒干扰问题。
    • 在包装团队中,脚本调试往往有很多专业知识,但是很少有C ++知识(很多人知道一些C#和PowerShell)。 开发人员可能更喜欢C#,但可以轻松处理JavaScript。

我确定的一件事情是, 托管代码自定义操作的可用性将导致人们在设置中做太多事情,而这些事情绝不应该在设置中完成 。 这完全是因为编码更容易,速度更快,并且所讨论的开发人员可能不了解应该如何进行正确的部署。 这不可避免地导致各种自定义操作的过度使用,并且随着自定义操作的复杂性引发意外错误,主要的部署问题也随之而来。