【问题标题】:How to assign path value to Directory in WIX?如何在 WIX 中为目录分配路径值?
【发布时间】:2018-01-26 15:10:29
【问题描述】:

在我的 WIX 项目中,我有一个类似这样的目录结构:

<Directory Id="TARGETDIR" Name="SourceDir">
  <Directory Id="INSTALLLOCATION" Name="FolderName">
   ...
  </Directory>
  <Directory Id="MYDIRECTORY" Name="SomeDifferentDirectory">
   ...
  </Directory>
</Directory>

这里INSTALLLOCATION代表我的程序的安装文件夹,但是我想另外创建一个安装目录之外的目录,例如D:\MyFolder1\MyFolder2,从上面的例子中我如何将此值分配给@987654325 @ 以便在安装完成后创建?

【问题讨论】:

  • 在下面添加了一些细节。
  • @SteinÅsmul 在下面提供了一个非常完整的答案,但我还想指出,这也得到了回答here

标签: wix windows-installer wix3.11


【解决方案1】:

我没有时间测试我在下面列出的选项,但它们应该是可行的技术可能性。希望其中一个选项令人满意。

但是,首先我不喜欢这种设置二级、顶级目录的方法——真的需要吗?你能解释一下这个场景吗?也许有更可靠的方法?

请参阅底部的“替代方案?”部分,了解我认为比“摆弄”目录属性更好的方法。如果我是你,我会读这个“替代品?”第一节 - 也许它会为您省去很多麻烦?

但第一部分涉及各种技术选项来满足您的要求:


设置目录属性

有很多方法可以设置目录属性,我想不到。正如我所说,我没有时间测试这些选项 - 发布未经测试的建议总是很疯狂,但您似乎可以帮助自己提供一些指导:

  1. AppSearch - 您可以在系统中搜索特定文件或注册表项,并将目录属性设置为找到的路径(如果有)。
    • 通常可以通过这种方式找到您需要的路径 - 并且在某种意义上也是可靠的,因为它是一个内置功能(因此比您自己的任何自定义构造都经过更好的测试)。
    • 您还可以添加自定义操作来验证找到的目录是否有效 - 如果需要的话。此类“验证数据”自定义操作可以非常安全,因为它们不会更改系统 - 但如果您不小心并允许它们返回错误代码或中止设置,它们仍然可能导致意外的运行时故障。
  2. Set Property Custom Action(自定义操作类型 51)。只需将路径设置为[ROOTDRIVE]MyFolder 之类的东西。
    • 如果有人这样做,我会因为质量原因导致包失败(这在技术上是可行的,但ROOTDRIVE 可能会根据每个驱动器上可用的磁盘空间切换到不同的路径 - 一点也不好)。
    • 了解可能性,寻找它,如果找到就修复它。不要使用它。阴暗的一面是诱人的。
    • 具有讽刺意味的是,老实说,将某些内容设置为[WindowsVolume]MyFolder - 可能确实有效,但我个人不喜欢它。首先,我不想在系统驱动器的顶级文件夹中安装任何内容。
    • 我相信 WiX 有 SetDirectory Element 用于此“设置属性”目的。我认为它可以为您完成所有自定义操作。一些自动魔法。但是我不确定此功能是否允许从命令行覆盖公共属性?
    • 如果您将某些内容设置为D:\MyFolder,您必须注意此路径可能会在某些时候意外丢失(从系统中删除驱动器、添加新驱动器 (?)、添加新 DVD 驱动器 (?)、手动驱动器号改变了,等等......)。
      • 这超出了正常的“设置属性”操作 - 它本质上是“硬编码”(参见下面的问题 5)。 硬编码是绝对不能接受的 - 对于任何具有通用分布的包。
      • 我更喜欢定位PersonalFolder(我的文档),然后将其重定向到 Windows 本身的 D:\。我相信如果在启动时找不到PersonalFolder,Windows 会为它分配一个新值。然后,Windows Installer 将仍然能够枚举目标文件夹,而不仅仅是卡住或崩溃。
  3. 将目录设置为在安装程序 GUI 的自定义对话框中公开的功能目录

    • 因为我从未使用过它,所以我很生气,但我认为这是一个可行的选择 - 但需要在所有安装模式(安装、修复、自我修复、卸载、修改、修补等...)中进行大量测试以确保它按要求工作。
      • 快速更新:我进行了冒烟测试,它可以工作,但我会说这并非易事。 在下一节中查看模拟 GUI 示例和一些 WiX sn-ps
    • 这涉及为设置到此功能目录的组件添加单独的功能。然后,您将 WiX 源中 FeatureElementConfigurableDirectory 属性设置为与保存目录路径的 PUBLICPROPERTY 相同。
    • 如果您使用对话框集 Mondo (&lt;UIRef Id="WixUI_Mondo" /&gt;) - 从“自定义”对话框,您现在应该能够从 WiX GUI 设置此目录。这里有一个使用 Visual Studio 更新 WiX 源文件以使用 Mondo 的分步示例:WiX installer msi not installing the Winform app created with Visual Studio 2017
    • 您所做的 GUI 选择(目录)将分配给您为该功能指定为 ConfigurableDirectory 的属性。
    • 您必须以某种方式将目录属性设置为对静默安装有意义的值 - 当跳过 GUI 时 - 或者如果在命令行上没有为该属性定义任何内容,您可以中止安装。
    • 我会在其中检查有效目录并防止出现一般性错误,例如安装到系统文件夹、直接安装到 C:\、安装到其他产品的现有文件夹等... - " ...users are amazingly creative when it comes to exercising a system in unexpected ways" - Grady Booch - 生活用词,多么酷的名字 - 和头发 - :-)。
  4. 一个常规的即时模式自定义操作(不是设置属性自定义操作),它通过调用 Session.Property = "SomeValue" 在代码。每种自定义操作类型的“属性集”略有不同(自定义操作类型:VBScript、C++、DTF / C# 等...See documentation from Advanced Installer 了解如何做到这一点)。

    • 我总是告诉人们避免自定义操作,读写自定义操作绝对是这样:Why is it a good idea to limit the use of custom actions in my WiX / MSI setups?
    • 但是,我确实使用只读自定义操作集来抑制错误,并且不返回在需要时回滚设置的错误。这使您能够在您认为合适的时候检查系统以确定为相关属性设置的内容。
    • 至关重要的是,此类即时模式只读自定义操作不需要回滚功能,因为它们不会对系统进行任何更改,它们也不会运行提升,并且它们中的大多数“存在于 GUI 序列中”并且用于从用户那里获取数据和设置 - 或检查目标系统的各种条件和状态 - 只是检查事物(如果跳过 GUI,它们通常在静默安装序列中也需要)。
    • 请记住,在静默安装模式下会跳过 GUI 序列,因此您的自定义操作必须同时存在于两个序列中。不过,您可以将其设置为只运行一次。
  5. 有些人甚至在属性表中硬代码路径,或者使用设置属性自定义操作在运行时将C:\ 分配给属性 - 完全不可接受。 这将打破 - 这只是时间问题。在没有 C:\ 驱动器的计算机上,它根本不会安装 - 对于初学者来说。

    • 不确定在属性表中设置的此类属性是否会在 directory resolutioncosting 期间被覆盖 - 我从未尝试过 - 这不是解决方案,我只想声明阻止其使用。

    • C:\ 或类似属性分配给属性的设置属性自定义操作似乎可以工作,但会以意想不到的方式崩溃。保证。

    • 再次重申:如果可以,请不要部署到单独的顶级文件夹。

  6. 我听说有些人 - 在公司的标准化环境中 - 使用 环境变量 来定义此类安装文件夹。我从未将其用于生产,从未尝试将其用于测试,也不喜欢将其作为一个选项。

请记住,公共属性可以在命令提示符下设置 - 因此可能会覆盖您添加的任何逻辑以自行设置。也许添加一个自定义操作来检查从命令行传入的值,如果错误,要么接受它,要么中止设置。


具有可配置功能目录的 WiX 安装程序

这是带有可配置功能目录的 WiX 安装程序的 GUI 屏幕截图:

上面看到的浏览按钮仅适用于指定了指向自定义目录属性的 ConfigurableDirectory 属性的功能(忽略上面屏幕截图中的 C:\ 条目 - 只是打嗝):

<!-- A standard feature -->
<Feature Id="ProductFeature" Title="MinimalShortcutTester" Level="1">
   <ComponentGroupRef Id="ProductComponents" />
</Feature>

<!-- A configurable directory feature -->
<Feature Id="FeatureDirectory" Title="FeatureDirectory" ConfigurableDirectory="MYCUSTOMDIR">
        <!-- your stuff here -->
</Feature>

在 WiX 源代码的其他地方,实际可配置的目录:

<Directory Id="MYCUSTOMDIR">
     <!-- Mock-up GUID that MUST be changed, custom target directories do not function with auto-GUIDs -->
     <Component Id="MyFile.exe" Guid="{00000000-0000-0000-0000-000000000000}" Feature="FeatureDirectory">
         <File Source="C:\SourceControl\MyFile.exe" />
     </Component>    
</Directory>

我会使用一个额外的自定义操作来很好地默认这个MYCUSTOMDIR 目录,或者检查用户所做的选择是否有效。这并不完全直截了当,但必须在每种情况下处理。

再想一想,我可能会使用set property custom action 将MYCUSTOMDIR 目录默认为PersonalFolder 的子文件夹,然后允许用户在安装时覆盖它。现在您必须回读用户选择的修改和修复(以及其他安装模式),否则您将默认为PersonalFolder 以及您在其他安装模式中指定的任何子文件夹。您可以将用户文件夹选择保留在注册表中,然后使用AppSearch(我认为大多数专业人士的偏好)将其读回,或者在自定义操作中完成所有操作。在所有安装模式下使这项工作正常工作可能具有挑战性。好好测试一下。

技术挑战:如果您将 MYCUSTOMDIR 的原始文件夹选择保留在注册表中并使用 AppSearch 回读,则必须确保设置您的设置属性自定义操作(用于如果没有设置值,则将默认值设置为MYCUSTOMDIR),这样如果属性已经从注册表中检索到值,它就不会运行。不是火箭科学,但可以很巧妙地做到正确 - 并且在所有安装模式下进行测试。如果您依赖标准结构而不是自定义操作,那么一旦您了解所涉及的“移动部件”,您通常会受益 - 首先您默认首次安装,因为尚未设置任何值(除非通过命令行设置值),然后您允许它在 GUI 中(或通过命令行)被覆盖,然后在安装过程中保留在注册表中,在下次启动(修复、修改、自我修复、升级、补丁)时,您读回保留的值并且不要让通过条件等设置默认值...

提供一个安全链接:Wix : Disable control in built-in dialog


替代方案?

如上所述,通过更好地理解替代方案,通常可以避免这些二级顶级目录层次结构。

检查替代方案的一些问题

  • 哪些文件将进入该二级顶级文件夹?数据文件?数据库?
  • 此类文件夹通常用于存储数据文件,有时使用的文件夹对于每个用户来说都是唯一的(即不是共享文件夹)。例如“我的文档”。
    • 在这些情况下,我喜欢让应用程序在启动时创建文件夹(将对此类文件夹具有写访问权限),然后从安装在某处的只读模板副本中将每个用户所需的任何文件复制到该文件夹在 %ProgramFiles% 下。
    • MSI 不适合部署用户配置文件。我在这里写了一些问题的摘要:Create folder and file on Current user profile, from Admin Profile。通常不清楚如何引用多次部署的计数文件,每个用户一次。
    • 我多次重复这个建议,但有时处理用户配置文件部署确实是一场噩梦。 非常常见的问题:(1) 意外的数据覆盖/重置,(2) 未能将用户配置文件复制到位,(3) 意外卸载修改的文件(读取:用户数据),(4)无法可靠地覆盖现有文件 - 同样的问题往往会重复。
  • 当然也有可能出于其他原因需要这样一个顶级文件夹,但我敢打赌,它将填充用户数据或用户可修改的文件。这准确吗?

【讨论】:

    猜你喜欢
    • 2021-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-12
    相关资源
    最近更新 更多