如何在WIX中为Directory分配路径值?

Myk*_*ych 0 windows-installer wix wix3.11

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

<Directory Id="TARGETDIR" Name="SourceDir">
  <Directory Id="INSTALLLOCATION" Name="FolderName">
   ...
  </Directory>
  <Directory Id="MYDIRECTORY" Name="SomeDifferentDirectory">
   ...
  </Directory>
</Directory>
Run Code Online (Sandbox Code Playgroud)

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

Ste*_*mul 5

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

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

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

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


设置目录属性

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

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

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

    • 我总是告诉人们避免自定义操作,对于读写自定义操作肯定是这样的:为什么限制在我的WiX/MSI设置中使用自定义操作是个好主意?.
    • 但是,我会使用只读自定义操作来抑制错误,而不会返回在需要时回滚设置的错误.这允许您根据自己的需要检查系统,以确定要对相关属性设置的内容.
    • 至关重要的是这种立即模式只读自定义操作不需要回滚功能,因为它们不进行系统更改,它们也不会升级,并且大多数"生活在GUI序列中"并用于从用户获取数据和设置- 或检查目标系统的各种条件和状态 - 只检查事物(如果跳过GUI,通常也需要在静默安装序列中使用它们).
    • 请记住,在静默安装模式下会跳过GUI序列,因此您的自定义操作必须同时存在于两个序列中.您可以将其调整为仅运行一次.
  5. 有些人甚至在属性表中硬编码路径,或者使用set属性自定义操作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>
Run Code Online (Sandbox Code Playgroud)

在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>
Run Code Online (Sandbox Code Playgroud)

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

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

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

投入一个用于保管的链接:Wix:在内置对话框中禁用控件.


备择方案?

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

有些问题需要检查替代方案:

  • 这个辅助顶级文件夹有哪些文件?数据文件?数据库?
  • 这些文件夹通常用于数据文件,有时使用的文件夹对每个用户都是唯一的(即不是共享文件夹).例如"我的文档".
    • 在这些情况下,我喜欢让应用程序在启动时创建文件夹(对这样的文件夹有写访问权限),然后从%ProgramFiles下安装的只读模板副本中复制每个用户所需的文件夹. %.
    • MSI不适合部署用户配置文件.我在这里写了一些问题的摘要:从管理员档案中创建当前用户档案中的文件夹和文件.通常不清楚如何引用多次部署的计数文件,每个用户一次.
    • 我重复这个建议太多次了,但有时处理userprofile文件部署确实是一场噩梦.非常常见的问题:(1)意外数据覆盖/重置,(2)无法复制userprofile文件,(3)意外卸载修改后的文件(读取:用户数据),(4)无法可靠地覆盖现有文件 -同样的问题往往会重演.
  • 当然也可能出于其他原因需要这样的顶级文件夹,但我敢打赌它将填充用户数据或用户可修改的文件.这准确吗?