3

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

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

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

4

1 回答 1

9

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

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

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

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


设置目录属性

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

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

    • 疯狂建议,因为我从未使用过它,但我认为这是一个可行的选择 - 但需要在所有安装模式(安装、修复、自我修复、卸载、修改、修补等)中进行大量测试以确保它可以按需要工作。
      • 快速更新:我做了一个冒烟测试,它可以工作,但我会说这不是微不足道的。请参阅下面下一节中的模拟 GUI 示例和一些 WiX 片段
    • 这涉及为设置到此功能目录的组件添加单独的功能。然后,您将 WiX 源中的ConfigurableDirectory属性设置为FeatureElement等于保存目录路径的 PUBLICPROPERTY。
    • 如果您使用对话框集Mondo ( <UIRef Id="WixUI_Mondo" />) - 从“自定义”对话框中,您现在应该能够从 WiX GUI 设置此目录。这里有一个使用 Visual Studio 更新 WiX 源文件以使用 Mondo 的分步示例:WiX 安装程序 msi not installed the Winform app created with Visual Studio 2017
    • 您所做的 GUI 选择(目录)将分配给您ConfigurableDirectory为该功能指定的属性。
    • 不知何故,您必须将目录属性设置为对静默安装有意义的东西 - 当跳过 GUI 时 - 或者如果在命令行上没有为该属性定义任何内容,您可以中止安装。
    • 我会在其中检查有效目录并防止出现一般性的疯狂行为,例如安装到系统文件夹、直接安装到 C:\、安装到其他产品的现有文件夹等...... - “ ......用户非常棒在以意想不到的方式锻炼系统时很有创意” - Grady Booch - 生活的话,多么酷的名字 - 和头发 - :-)。
  4. 一个常规的即时模式自定义操作(不是设置属性自定义操作),它通过在代码中某处调用Session.Property = "SomeValue" 来设置属性。每种类型的自定义动作类型对“属性集”的执行方式略有不同(自定义动作类型:VBScript、C++、DTF / C# 等...有关如何执行此操作,请参阅 Advanced Installer 的文档)。

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

    • 不确定是否会在属性表中设置这样的属性,directory resolution并且costing- 我从来没有尝试过 - 这不是一个解决方案,我只想声明以防止它的使用。

    • 设置属性自定义操作分配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很好地默认这个目录,或者检查用户所做的选择是否有效。这并不完全直截了当,但必须在每种情况下处理。

再想一想,我可能会使用 aset 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)无法可靠地覆盖现有文件 -同样的问题往往会重复。
  • 当然,出于其他原因也可能需要这样的顶级文件夹,但我敢打赌,它将充满用户数据或用户可修改的文件。这是准确的吗?
于 2018-01-28T20:19:35.360 回答