未为静默安装设置 Wix 目录 ID 符号值

Wix Directory Id symbol value not set for quiet install

我的 WIX 项目有问题。当我进行正常的 GUI 安装时,一切都按预期工作。但是,当我执行 /q(安静)安装时,我的目录 ID 符号之一没有被设置。 (可能是因为安静安装没有 UI 序列。但是,我很困惑我到底做错了什么。)

在我的 Product.wxs 中,我有一个这样开始的目录树:

<Directory Id="TARGETDIR" Name="SourceDir">
  <Directory Id="ProgramFilesFolder" Name="PFiles">
    <Directory Id="COMPANY" Name="Company">
      <Directory Id="BRANCHALL" Name="Branch">
        <Directory Id="INSTDIR" Name="Replaced">
          <Directory Id="BINDIR" Name="Bin">

就在那下面我设置目录,因为我们的应用程序安装将安装 ID 作为用户输入字符串,它成为目录路径的一部分。 (它也可以在静默安装命令行中传递。)因此,就在上面的目录树定义下,我有:

<SetDirectory Id="INSTDIR" Value="[BRANCHALL]\[INSTID]" Sequence="execute" />
<SetDirectory Id="BINDIR" Value="[BRANCHALL]\[INSTID]\Bin" Sequence="execute" />

...等等

当我进行静默安装时,日志显示如下:

MSI (s) (F8:84) [20:55:29:702]: Product: ProductName - Instid -- Error 1606. Could not access network location \Instid.
Error 1606. Could not access network location \Instid.
Action ended 20:55:29: CostFinalize. Return value 3.
Action ended 20:55:29: INSTALL. Return value 3.
Property(S): UpgradeCode = {9AC2D8DF-5EF7-440B-A0D2-4A97FA62368C}
Property(S): INSTID = Instid
Property(S): BRANCHALL = C:\Program Files (x86)\Company\Branch\
Property(S): POWERSHELLEXE = C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe
Property(S): BINDIR = \Instid\Bin

请注意,虽然记录的 BRANCHALL 值是正确的,但 BINDIR 符号缺少 BRANCHALL 值,但确实正确获取了 INSTID 值。

我 运行 GUI(非静默)安装时的相同日志片段:

Property(C): UpgradeCode = {9AC2D8DF-5EF7-440B-A0D2-4A97FA62368C}
Property(C): INSTID = Instid
Property(C): BRANCHALL = C:\Program Files (x86)\Company\Branch\
Property(C): POWERSHELLEXE = C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe
Property(C): LicenseAccepted = 1
Property(C): BINDIR = C:\Program Files (x86)\Company\Branch\Replaced\Bin\

奇怪的是,BRANCHALL 属性 进行了详细说明,而 INSTID 则没有。然而安装工作正常并将所有文件放在正确的文件夹中。所以INSTID一定是在msiexec做了这些日志之后详细说明的

如果缺少所需信息,请询问我。我有点困惑,当然不是 WIX 专家。谢谢!

我现在没有时间写完整的答案,但这里有一些提示:

技术: 当你在你的set 属性 / set directory custom action中引用另一个目录属性 ,我相信您需要 运行 CostFinalize 之后的自定义操作才能将另一个 属性 设置为任何值。执行此操作时,需要使用 Type 35 custom action rather than a Type 51 custom action. See MSDN: Changing the Target Location for a Directory。我的 smoke test 使用 Type 35 action 似乎有效。我明天会测试更多,并更详细地更改此答案。


N.B!未正确测试:

<SetProperty Id="INSTDIR" Value="[BRANCHALL]\[INSTID]" After="CostFinalize" />

您可以尝试使用上述标记代替当前的 SetDirectory 元素。编译 MSI 后,您必须 "hotfix" 将 CustomAction Table 中的自定义操作从 Type 51 更改为 Type 35(只需将 Type 列中的 51 更改为 35)- 然后 运行 测试安装。使用 Orca 或等效工具来执行此修补程序。 我只是添加这个所以你可以试试,我还没有正确测试它.


替代方案?:总的来说,我建议您不要以这种方式重定向文件夹属性。我发现它不可靠并且充满了意想不到的问题。事实上,我看不出这种方法如何允许您多次安装 MSI - 由于总体 Windows 安装程序设计(不允许完全并发安装)。如果您想多次安装同一个 MSI,那么您可能需要浏览一些预先存在的答案:

我不知道你是否在公司环境中,但 App-V 被很多公司使用。这不是我的菜(至少目前是这样),但应该提一下,以便您确定什么可以满足您的要求(我们仍然需要正确理解)。

此信息不完整,明天会检查。

要理解这一点,首先要意识到您的日志摘录是从末尾开始的,但它反映了按特定顺序发生的各种操作。正如 Stein 在他的回答中提到的,您编写的 SetDirectory elements 是作为设置属性的自定义操作实现的。具体来说,<SetDirectory Id="INSTDIR" Value="[BRANCHALL]\[INSTID]" Sequence="execute" /> 将名为 INSTDIR 的 属性 设置为 CostFinalize 之前格式化 [BRANCHALL]\[INSTID] 的值。

这是一个问题,因为在CostFinalize构建目录树之前,BRANCHALL没有任何价值。当显示 UI 时,CostFinalize 在每个序列中执行一次 运行s。第一个填充 BRANCHALL,并使用 INSTDIR 的默认路径。第二个(执行)序列然后使用填充的 BRANCHALL 来确定 INSTDIR,从而掩盖了问题。但如果没有 UI,则使用空值。如果您搜索属性值更改的位置,您应该能够在详细日志中确认这一点。

那么解决方法是什么?看起来,至少在您的摘录中,您可以仅使用预定义的属性来预测 BRANCHALL 的默认值,因此应该能够相应地修改您的 SetDirectory 创作:

<SetDirectory Id="INSTDIR" Value="[ProgramFilesFolder]Company\Branch\[INSTID]" Sequence="execute" />
<SetDirectory Id="BINDIR" Value="[ProgramFilesFolder]Company\Branch\[INSTID]\Bin" Sequence="execute" />

但是,这样做有一个潜在的问题。如果您允许最终用户更改 UI 中 BRANCHALL 中使用的任何位置,这将覆盖它。如果这种情况对您很重要,我相信指定 Sequence="first" 而不是 Sequence="execute" 会解决这个问题。 (但是你必须 运行 一些测试来确定这有帮助。)此外,对于希望覆盖它的静默安装,你可能需要记录必须指定的更完整的属性集以及如何指定他们。因此,您可能需要向此 SetDirectory 元素添加一些条件,如 Not INSTDIR/Not BINDIRNot I_CHANGED_THE_DIRECTORIES.


如果可能,我会推荐一种不同的方法:将 INSTID 的值放在目录 table 中,而不是使用自定义操作来覆盖不正确的值。主要的缺点是这需要创建并使用转换来设置它,而不是仅仅在命令行上传递一个值。但好处是 Windows 安装程序会像往常一样处理目录。