【问题标题】:WIX Installer: Prevent installation on Windows Server 2012 R2WIX 安装程序:阻止在 Windows Server 2012 R2 上安装
【发布时间】:2018-09-15 16:13:21
【问题描述】:

我有一个只能安装在 Windows Server 2016(或更高版本)上的 WIX 项目。

查看 Microsoft 文档,VersionNT 用于:

Windows Server 2016 是 603, Windows Server 2012 是 602。

从未提到过用于 Windows Server 2012R2 的 VersionNT。

当我使用下面的代码行时:

<Condition Message="!(loc.RequireServer2016)"><![CDATA[INSTALLED OR (VersionNT >= 603)]]></Condition>

它仍然允许我在 Windows Server 2012R2 上安装。

如何将我的软件的安装限制为仅 Server 2016 并阻止它安装在 Server 2012R2 上?

【问题讨论】:

  • 为什么不是 server 2012 r2?你支持2008 r2吗?只有2016+?我喜欢阻止操作系统中缺少的功能,而不是操作系统的名称/版本。

标签: wix windows-installer installation windows-server-2012-r2 windows-server-2016


【解决方案1】:

INSTALLED 应该是 InstalledProperties are case sensitive 并且你必须在你的条件下解决这个问题 - 否则这部分条件永远不会正确 - 即使安装了产品。

实际上,其余的条件看起来还可以。只是一些确定问题所在的想法:

  1. WiX 源元素:您确定在 WiX 源中的正确位置包含此条件吗?

  2. 无版本:在Windows 10 中检测操作系统版本的方式发生了巨大变化。我不知道这是否也会影响Windows Server 2012R2

    • 似乎总体思路是 Windows 现在是“无版本常青”(一个术语如何) - 这意味着 VersionNT 根本不一定报告正确的操作系统版本!
    • 请阅读此答案,而不是我在这里重复:Windows 10 not detecting on installshield

为了确定您的设置中VersionNT 的真正值,我将使用两种方法之一在运行时检查属性。后一个选项(日志记录)通常更快更容易,而第一个选项还允许您在设置运行时评估复杂条件,并使用 Session.EvaluateCondition method 在运行时显示它们是真还是假(我使用此方法调用时条件复杂且令人困惑,我想要一些运行时证明它们的行为符合我的预期):

  1. 属性调试器 VBScript:我有一个属性调试器 VBScript,用于在运行时为 MSI 文件显示一堆属性值,并在运行时评估条件以显示他们是否评估为真 - 如上所述。如果我是你,我会使用这样的脚本在运行时显示VersionNT(以及你想要检查的任何其他属性或条件)。

    • It is recommended that you don't use VBScript for production setups - debugging onlyRobWiX 的创建者 - 我同意他的所有反脚本论点,但我个人仍然认为 VBScript 对调试很有用 - 快速、简单且无需编译的嵌入式源代码.设置一个完整的编译自定义操作只是为了检索一些属性进行测试非常耗时(但使用 C++ 等“真实代码”进行调试会更好也更容易)。
    • 在企业环境中,由于 嵌入式源代码,VBScript 得到了广泛的使用 - 您总能找到嵌入在 MSI 中的真实自定义操作源 - 在您编译源的编译自定义操作中并非如此from 可能不可用(由于所有技术事物固有的混乱 - 在现实世界中) - 这确实非常糟糕。
    • 另一个好处是 VBScript 的简单性,以及企业应用程序打包者如何比 C++/C# 更好地掌握复杂性。但整体脚本自定义操作总是会导致 Rob 提到的问题(防病毒阻止、糟糕的调试和缺乏适当错误处理的编码乏善可陈)。
    • 至关重要的是,您将在企业部署方案中控制安全软件/防病毒。您可以以合乎逻辑的方式处理问题并进行调整,直到包可靠地部署。
    • 最后,企业台式机是 SOE - 标准化平台,其可变性远低于普通 PC(其状态可能更加多样化,因此会出现更多部署问题)。
    • 真正的问题基本上完全是自定义操作,它们很容易出错:Why is it a good idea to limit the use of custom actions in my WiX / MSI setups? 我猜想的信息比你需要的多得多。 故事的寓意对我来说是:使用最快完成工作的任何方法,但不要认为脚本足以用于生产代码以供全球分发
    • 对于企业部署,应消除即席脚本自定义操作,转而支持经过充分测试的 C++ 自定义操作,这些操作具有由自定义 MSI 表驱动的完全回滚支持,从而产生对安装期间应发生的情况的完整声明。
  2. 记录:只需为设置创建一个日志文件并检查其中的VersionNT 的值。我喜欢为所有设置启用日志记录,如下所述:installsite.org on how to do logging - 请参阅“机器上的所有设置全局”部分)。尽管性能受到影响,我总是在TEMP folder 中准备好一个日志文件以进行调试。相同的链接也将向您展示如何仅为单个安装制作临时日志(本质上是:msiexec.exe /i "c:\filename.msi" /QN /L*V "C:\msilog.log" REBOOT=R - 带有日志记录和禁止重启的静默安装 - even more logging info)。


Property Debugger Demo:这超出了您的要求,但我认为您可能很难为您的服务器部署调试此问题和类似问题,我想快速演示如何在 VBScript 中评估 MSI 条件。

您的上述情况通常过于简单,无法解决此问题,但这是非常复杂情况下的通用方法 - 例如,当您只想在修复或重大升级启动卸载时运行自定义操作时 - 证明总是在测试中,不管你怎么想。

在运行时使用 VBScript 评估您的条件:

MsgBox "Condition: " & CBool( Session.EvaluateCondition("Installed OR (VersionNT >= 603)"))

这样的 VBScript 自定义动作可以根据需要插入到不同的序列和不同的位置。属性值可能会有所不同,具体取决于您的排序 (!) 以及您所处的安装模式installuninstallrepairmodifyself-repairmajor upgrade(涉及一个正在安装和一个正在卸载的 MSI)、minor upgrademinor upgrade patchmajor upgrade patchetc...)以及您是否在 deferredimmediate 中运行 context 或者您是在 静默 还是 交互式 运行,以及我忘记的任何变量 - MSI 中有很多活动部件。例如,如果您在 UI 序列的开头插入自定义操作,则 AppSearch 尚未运行,并且某些属性尚未设置。如果需要,您还可以在administrative-advertisement-installation 序列中插入属性调试结构。

也许还有一些用于测试目的的进一步条件:

  • "NOT Installed AND NOT WIX_UPGRADE_DETECTED"
  • "NOT Installed AND NOT REMOVE~="ALL""

还有一些由于复杂性而需要测试的内容 (not my conditions, they are from here):

  • Installed AND (NOT REMOVE="ALL" OR UPGRADINGPRODUCTCODE)
  • NOT Installed OR Installed AND (NOT REMOVE="ALL" OR UPGRADINGPRODUCTCODE)

我希望这是一个清晰的概念。我有一个用于此类属性调试的 VBScript,但它太大而且太乱放在这里。

【讨论】:

    【解决方案2】:

    根据这篇关于 Windows 10 和 Server 2016 的 VersionNT 值的文章:

    https://support.microsoft.com/en-us/help/3202260/versionnt-value-for-windows-10-and-windows-server-2016

    我会从以下条件开始:

    VersionNT=603 和 MsiNTProductType > 1

    后者表示服务器系统:

    https://msdn.microsoft.com/en-us/library/windows/desktop/aa370329(v=vs.85).aspx

    除此之外,查看 WindowsBuild 属性以查看它是否具有对 Server 2016 有用的值(或可用于排除 Server 2012 的值)。您还可以查看调用 GetSystemMetrics 的自定义操作:

    https://msdn.microsoft.com/en-us/library/windows/desktop/ms724385(v=vs.85).aspx

    查看 SM_SERVERR2 是否设置在 2012 年。

    您不需要包含 Installed 属性的条件。首次安装时,未设置 Installed 值。如果您尝试再次安装相同的 MSI,您将无法达到启动条件,因为 Windows 将看到此特定 ProductCode 已安装并进入维护模式(修复、卸载、功能更改类型的东西)。所以不清楚为什么你认为你需要它。如果您需要确保启动条件仅适用于初始安装,请将条件“未安装”添加到 UI 中的 LaunchConditions 操作并执行序列。

    【讨论】:

    • 使用“VersionNT=603 和 MsiNTProductType > 1”仍会让用户安装 Windows Server 2012R2。这是我现在使用的确切代码。我想阻止在 Server 2012 R2 上安装。
    • 嗨菲尔。我认为包含 OR'd Installed 属性是为了在原始安装后强制条件始终为真,以便在修改、修复或卸载时启动条件永远不会为假(这将是一个带有不可卸载包的 catch 22 -maybe see this answer)。假设条件检查安装后已卸载的运行时,则产品将拒绝卸载,因为启动条件为假。我认为这 Installed tweakMensching / Arnson 特别节目 :-)。去蝙蝠车。
    • Stein:我通常看到这个问题通过 UI 中的 LaunchConditions 操作上的“未安装”条件解决,并执行序列以避免混淆实际条件的复杂值。
    • 有道理 - 应该是标准的?在修改、修复、修补或卸载模式下运行启动条件是否有意义?我想如果(托管)自定义操作缺少运行时,那么它们无论如何都会崩溃?我发现启动条件有问题。
    猜你喜欢
    • 1970-01-01
    • 2016-08-01
    • 1970-01-01
    • 2017-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-19
    相关资源
    最近更新 更多