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

问题描述:

我最近被分配来更新我们的项目安装程序以在Windows 10上运行,并且在如何使其运行方面遇到了一些问题。我对安装程序没有经验,并且正在不仅熟悉过程,而且熟悉我们的项目如何处理它。Windows安装程序在Win 10上失败,但不是Win 7在使用WIX

截至目前,安装程序可以在我们的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. 

我已经研究过的错误,发现这个:Error 1603

我寻找到页面上的解决方案,但所有这一切应该是。我们以相同的方式在Win 10和Win 7虚拟机上以相同的权限运行安装程序。

我怀疑这将有足够的信息来获得任何具体的反应,所以我比任何东西我都在寻找建设性的建议如何看看以及如何弄清楚。我可以发布更多详细信息,但信息量如此之大,我不知道如何挑选真正相关的内容。

+1

我认为我们需要整个日志文件(详细)来做出任何进展。也许你可以在某处上传它?如果没有,请尝试[** Rob Mensching的寻找“价值3”的技巧**](http://robmensching.com/blog/posts/2010/8/2/the-first-thing-i-do-与-AN-MSI-日志/)。这应该会发现任何严重的错误。如果您发现任何问题,请发布。您在提供的日志中看到的错误看起来像[此问题](https://stackoverflow.com/questions/25418965/error-4-select-message-from-error-where-error-1707-also-1709) 。只是一个缺乏“错误”表(请参阅链接答案的底部)。 –

+1

首先要检查的明显罪魁祸首是包中的任何**自定义操作**或者您可能正在使用的任何**高级WiX功能**。有了这些神秘的错误,我经常使用“** flush to log **”选项来确保日志文件连续写入。这确保了崩溃进程不会导致日志缓冲区丢失。像这样记录:''msiexec.exe/I“App.msi”/ L * V! msilog.log“'(感叹号是关键)。 –

+0

Hi @SteinÅsmul感谢您的回复。我不认为我可以发布完整的未经编辑的日志文件,而不用重新编辑一些信息。但是,我能够使用该“技巧”找到返回值3。我们在运行PowerShell安装脚本的WIX文件中有某种自定义操作。尝试运行此自定义操作/脚本时发生该错误;它抱怨说,它“PowerShell无法找到注册表项”。我正在验证虚拟机有PowerShell(它应该,但我目前没有访问权限)。谢谢您的帮助! – Caboose

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


答案

依赖于像PowerShell中缺少运行时肯定会触发回滚。 MSI为某些脚本自定义操作托管自己的运行时(active scripting)。例如VBScript和JavaScript。为了可靠的部署,建议使用的所有自定义操作都是自包含的最小依赖性C++ dll或可执行文件(win32)或(较不可取的)VBScript或JavaScript(如果使用Installshield,请参见Installscript - 请参阅下面的详细信息)。

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

这就是真实答案的结尾:-)。下面是一些“详细的思考”,以便你制作一个用于一般分发的软件包(而不仅仅是你自己公司内部部署的软件包)。如果我是你,即使只在内部进行部署,我也会阅读它,PowerShell自定义操作可能是一个冲调部署问题,口径为

托管代码和脚本都有问题。 PowerShell同时有效。 Here is Rob Mensching's blog on why script custom actions are bad。从本质上讲:脚本很脆弱,缺乏语言功能,很难调试,反病毒产品经常会阻止它们。阅读博客。和here is Aaron Stebner's blog on why managed code is bad。从本质上讲,当你依赖.NET框架时,你不能保证有一个适当的运行环境。


放牧,沉思

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

如果您正在的MSI一般分配给任何的电脑随时随地,我会采取PowerShell脚本转换成别的东西的时间。最好是一个C++ DLL - 我发现它最可靠。没有依赖性可言或层依赖。即使你使用Installshield,也可以接受InstallScript(它可以在没有预先安装的运行时的情况下运行 - 这极大地提高了它的可靠性和实用性 - 尽管它的语法比较陈旧,但是它是一种钝语言。被低估 - 它完成这项工作,并且比C++简单)。

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

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


如果我猜我会说,Windows安装程序可能会被更新为能够举办了自己的PowerShell运行时 - 但是这仅仅是猜测。我不确定技术细节 - 看起来需要整个.NET运行时?如果你问我,我仍然会更喜欢JavaScript到PowerShell脚本,但是我意识到你可能会承诺将PowerShell作为公司标准?而且,总是比VB脚本更喜欢使用JavaScript,因为它具有看起来像异常处理(VB脚本完全缺乏)的东西。

罗布Mensching克里斯画家菲尔·威尔逊鲍勃Arnson,可能其他人也(我不知道对脚本Stefan Kruger's位置,或罗伯特·迪考的视图) - 会杀了我这,但这里是一个JavaScript自定义操作的模板(未经我测试,但看起来不错):How to debug an MSI Custom Action that is implemented in Javascript?如果我可以脱口而出:现在什么都比PowerShell更好 - 甚至是JavaScript。

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

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


推荐自定义操作执行

我写了的“建议”的自定义操作执行摘要。它变成了很长时间没有说多少 - 我删除它。取而代之的是,这里是我的自定义操作执行喜好的名单(按递减耐用性和可靠性的顺序排列):

  1. C++ DLL
  2. INSTALLSCRIPT(只的InstallShield)
  3. 的JavaScript
  4. VB脚本
  5. C#DTF
  6. PowerShell

摘要:

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

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

+0

再次感谢您的详细回复。不幸的是,我仅限于PowerShell,现在一般情况下它将如何保持。我想我已经查明了为什么会发生这种情况,看起来这可能是一个愚蠢的问题。我们的虚拟机显然有PS,但不是2.0版本。我们做了注册表检查,发现PS,但随后我们在setProperty标志: 'VALUE =” " [POWERSHELLEXE] " -Version 2.0 ...' 我不知道是否可以删除该版本标志,或以某种方式基于哪个版本是有条件的? – Caboose

+1

是的,我认为它是这样的。将来PowerShell可能是MSI文件中更“可接受的”脚本类型,但是如果可以的话,它总是喜欢最小的依赖关系(win32) - 特别是如果你制作一个包到大规模发布到不同的机器上的包,下面是一个关于[部署的复杂性]的简介(https://stackoverflow.com/a/12101548/129130)(从底部开始)。部署错误是累积**,**调试很困难**和**目标机器**有各种**不可预知的状态**。您正在处理** inte间歇性的错误**。 –

+1

我使用C#/ DTF和CustomAction.config文件,允许在.NET 2.0-4.7上运行。偶尔,如果确实需要,我会用它来托管一个powershell管道。 2017年绝对没有ActiveScript(VB/JS)自定义操作的地方。 –