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

时间:2018-01-26 15:10:30

标签: wix windows-installer wix3.11

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

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

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

1 个答案:

答案 0 :(得分:5)

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

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

请参阅&#34; 替代方案?&#34;我认为这是一个更好的方法而不是&#34;摆弄&#34;目录属性。如果我是你,我会读到这个&#34;替代品?&#34;第一节 - 也许它可以为你节省很多麻烦?

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

设置目录属性

有许多方法可以设置目录属性。正如我所说的,我还没有&#39;吨有时间来检验这些选项 - 它总是疯狂张贴未经检验的建议,但你似乎喜欢一个人,谁可以帮助自己与一些指针:

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

    • 疯狂的建议,因为我从来没有用过它,但它是一个可行的选择,我认为 - 但要求在所有安装模式显著测试(安装,修复,自我修复,卸载,修改,修补,等...)确保它按预期工作。
      • 快速更新:我做了一次烟雾测试,但它确实有效,但我要说的并不是一件轻而易举的事。 请参阅下面的下一部分中的模拟GUI示例和一些WiX片段
    • 这涉及为设置到此功能目录的组件添加单独的功能。然后,将WiX源中ConfigurableDirectory的{​​{1}}属性设置为等于保存目录路径的PUBLICPROPERTY。
    • 如果您使用对话框 Mondo FeatureElement),您现在应该能够从WiX GUI设置此目录 - 来自&#34; 自定义&#34;对话。有一个循序渐进的示例使用Visual Studio更新WiX源文件以在此处使用Mondo:WiX installer msi not installing the Winform app created with Visual Studio 2017
    • 您所做的GUI选择(目录)将分配给您为该功能指定为<UIRef Id="WixUI_Mondo" />的属性。
    • 不知何故,您必须将目录属性设置为静默安装有意义的内容 - 跳过GUI时 - 或者如果在命令行上没有为属性定义任何内容,则可以中止安装。
    • 我会检查一个有效的目录,并防止一般的疯狂,如安装到系统文件夹,直接安装到C:\,安装到其他产品的现有文件夹等... - &#34; ...users are amazingly creative when it comes to exercising a system in unexpected ways &#34; - Grady Booch - 生活的话,多么酷的名字 - 和头发 - : - )。
  4. 常规,即时模式自定义操作(不是设置属性自定义操作),通过调用 Session.Property =&#34设置属性; someValue中&#34;代码中的某个地方。每种类型的自定义操作类型执行此操作&#34;属性设置&#34;略有不同(自定义操作类型: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序列&#34;并用于从用户获取数据和设置 - 或检查目标系统的各种条件和状态 - 只检查事物(如果跳过GUI,通常也需要在静默安装序列中使用它们)
    • 请记住,在静默安装模式下会跳过GUI序列,因此您的自定义操作必须同时存在于两个序列中。您可以将其调整为仅运行一次。
  5. 有些人甚至在属性表中使用硬代码路径,或使用set属性自定义操作在运行时将ConfigurableDirectory分配给属性 - 根本不可接受。 这会打破 - 这只是一个时间问题。在没有C:\驱动器的计算机上,它根本不会安装 - 对于初学者来说。

    • 不确定在C:\directory resolution期间是否会覆盖属性表中设置的此类属性 - 我从未打扰过尝试 - 这不是解决方案而我只是想要说明要防止其使用。

    • 分配costing或类似属性的设置属性自定义操作似乎有效,但会以意想不到的方式爆炸。保证。

    • 同样:如果您可以提供帮助,请不要部署到单独的顶级文件夹。

  6. 我听说有些人 - 在企业标准化环境中 - 使用环境变量来定义此类安装文件夹。我从未将它用于生产,从未尝试过进行测试,也不喜欢它作为一种选择。

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

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

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

    enter image description here

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

    C:\

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

    <!-- 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>
    

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

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

    投入保管的链接:Wix : Disable control in built-in dialog

    替代?

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

    检查替代方案的一些问题

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