我没有时间测试下面列出的选项,但它们应该是可行的、技术上的可能性。希望其中一个选项能够令人满意。
但是,首先: 我不喜欢这种设置二级顶级目录的方法 - 真的需要吗?你能解释一下这个场景吗?也许有更可靠的方法?
参见“备择方案?”部分,我认为这是比“摆弄”目录属性更好的方法。如果我是你,我会首先阅读这个“替代方案?”部分 - 也许它可以为您节省很多麻烦?
但第一部分涉及各种技术选项来完成您的要求:
设置目录属性
设置目录属性的方法有很多种,我一时想不起来。正如我所说,我还没有时间测试这些选项 - 发布未经测试的建议总是很疯狂,但你似乎可以为自己提供一些指导:
-
AppSearch http://wixtoolset.org/documentation/manual/v3/xsd/wix/appsearch.html - you can search the system for a specific file or registry entry and set the directory property to the path found (if any).
- 通常,您需要的路径可以通过这种方式找到 - 并且也可靠,因为它是一个内置功能(因此比您自己的任何自定义构造都经过更好的测试)。
- 如果需要,您还可以添加自定义操作来验证找到的目录是否有效。此类“验证数据”自定义操作可以非常安全,因为它们不会更改系统 - 但如果您不小心并允许它们返回错误代码或中止设置,它们仍然可能导致意外的运行时故障。
- A Set Property Custom Action https://msdn.microsoft.com/en-us/library/windows/desktop/aa368237(v=vs.85).aspx (Custom Action Type 51). Just set the path to something like
[ROOTDRIVE]MyFolder
.
- 如果有人这样做,我会因为质量原因而使包裹失败(技术上是可能的,但是根驱动器 https://msdn.microsoft.com/en-us/library/windows/desktop/aa371372(v=vs.85).aspx可能会根据每个驱动器上的可用磁盘空间切换到指向不同的路径 - 一点也不好)。
- 了解可能性,寻找它,如果发现它就修复它。不要使用它。黑暗的一面很诱人。
- 讽刺的是,如果我诚实的话,设置一些东西
[WindowsVolume]MyFolder
- 可能确实有效,但我个人不喜欢它。我首先不希望将任何内容安装到系统驱动器上的顶级文件夹中。
- 我相信 WiX 有
SetDirectory Element
为了这个“设置属性”的目的。我认为它可以为您完成所有自定义操作。一些自动魔法。但是我不确定此功能是否允许从命令行覆盖公共属性?
- If you set something to
D:\MyFolder
you have to be aware that this path could at some point be missing unexpectedly (drive removed from system, new drive added (?), new DVD drive added (?), drive letter manually changed, etc...).
- 这超出了正常的“设置属性”操作 - 它本质上是“硬编码”(请参阅下面的问题 5)。硬编码是永远不可接受的- 适用于任何通用分发包。
- 我更愿意瞄准
PersonalFolder
(我的文档),然后将其重定向到 Windows 本身的 D:\。我相信Windows随后会分配一个新值PersonalFolder
如果在启动时找不到它。然后,Windows Installer 仍然能够枚举目标文件夹,而不仅仅是卡住或崩溃。
-
将目录设置为特征目录在安装程序 GUI 的自定义对话框中公开。
- Mad to suggest since I have never used it, but it is an viable option I think - but requires significant testing in all installation modes (install, repair, self-repair, uninstall, modify, patching, et...) to make sure it works as desired.
- 快速更新:我做了一个冒烟测试,它有效,但我想说这并不是一件小事。请参阅下面下一节中的模拟 GUI 示例和一些 WiX 片段.
- 这涉及到为设置到此功能目录的组件添加单独的功能。然后你设置
ConfigurableDirectory
的属性FeatureElement
在你的 WiX 源中等于保存目录路径的 PUBLICPROPERTY。
- 如果您使用对话框集,您现在应该能够从 WiX GUI 设置此目录Mondo (
<UIRef Id="WixUI_Mondo" />
) - 来自 ”Custom” 对话框。这里有一个使用 Visual Studio 更新 WiX 源文件以使用 Mondo 的分步示例:WiX 安装程序 msi 未安装使用 Visual Studio 2017 创建的 Winform 应用程序 https://stackoverflow.com/questions/47970743/wix-installer-msi-not-installing-the-winform-app-created-with-visual-studio-2017/47972615#47972615.
- 您所做的 GUI 选择(目录)将分配给您指定的属性
ConfigurableDirectory
对于该功能。
- 不知何故,您必须将目录属性设置为对静默安装有意义的内容(当跳过 GUI 时),或者如果在命令行上没有为该属性定义任何内容,您可能会中止安装。
- 我会在其中检查有效目录并防止普遍的疯狂行为,例如安装到系统文件夹、直接安装到 C:\、安装到其他产品的现有文件夹等...... - ”" - 格雷迪·布奇 https://en.wikipedia.org/wiki/Grady_Booch- 赖以生存的话语,多么酷的名字 - 和头发 - :-)。
-
A 常规、即时模式自定义操作(不是设置属性自定义操作)它通过调用来设置属性会话.属性= 代码中某处的“SomeValue”。每种类型的自定义操作类型的“属性集”略有不同(自定义操作类型:VBScript、C++、DTF / C# 等...请参阅高级安装程序的文档 https://www.advancedinstaller.com/user-guide/set-windows-installer-property-custom-action.html了解如何做到这一点)。
- 我总是告诉人们避免自定义操作,对于读写自定义操作来说绝对如此:为什么在 WiX / MSI 设置中限制自定义操作的使用是个好主意? https://stackoverflow.com/questions/46179778/why-is-it-a-good-idea-to-limit-the-use-of-custom-actions-in-my-wix-msi-setups/46179779#46179779.
- 但是,我确实使用只读自定义操作集来抑制错误,并且不返回在需要时回滚设置的错误。这使您能够在您认为合适的情况下检查系统,以确定对相关属性设置什么。
- 至关重要的是这样的立即模式只读自定义操作不需要回滚功能由于它们没有对系统进行任何更改,因此它们也不会提升运行权限,并且大多数“存在于 GUI 序列中”,用于从用户获取数据和设置 - 或检查目标系统的各种条件和状态 -只是检查东西(如果跳过 GUI,静默安装序列中通常也需要它们)。
- 请记住,在静默安装模式下会跳过 GUI 序列,因此您的自定义操作必须存在于两个序列中。不过,您可以将其设置为仅运行一次。
-
有些人甚至硬代码路径在属性表中,或使用设置属性自定义操作来分配C:\
在运行时的属性 - 根本不可接受。这会打破——这只是时间问题。对于初学者来说,在没有 C:\ 驱动器的计算机上,它根本不会安装。
不确定在属性表中设置的此类属性是否会在期间被覆盖directory resolution
and costing
- 我从来没有费心去尝试 - 这不是一个解决方案,我只是想声明这一点以防止其使用。
设置属性自定义操作分配C:\
或类似的财产似乎会起作用,但会以意想不到的方式爆炸。有保证。
再次强调:如果可以的话,请不要部署到单独的顶级文件夹。
我听说有些人 - 在公司、标准化环境中 - 使用环境变量定义此类安装文件夹。我从未将它用于生产,从未尝试过将其用于测试,也不喜欢将其作为一种选择。
请记住,公共属性可以在命令提示符下设置 - 因此可能会覆盖您添加的任何逻辑以自行设置。也许添加一个自定义操作来检查来自命令行的值,如果错误则接受它或中止设置。
具有可配置功能目录的 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:禁用内置对话框中的控制 https://stackoverflow.com/questions/48377866/wix-disable-control-in-built-in-dialog/48403443#48403443.
备择方案?
如上所述,这些二级顶级目录层次结构通常可以通过更好地理解替代方案来避免。
检查替代方案的一些问题:
- 哪些文件将进入该辅助顶级文件夹?数据文件?数据库?
- Often such folders are for data files, and sometimes the folder used is unique for each user (i.e. not a shared folder). For example "My Documents".
- 在这些情况下,我喜欢让应用程序在启动时创建文件夹(将具有对此类文件夹的写访问权限),然后从安装在 %ProgramFiles 下某处的只读模板副本将每个用户所需的任何文件复制到该文件夹中%。
- MSI 不太适合部署用户配置文件。我在这里写了一些问题的总结:从管理员配置文件中在当前用户配置文件上创建文件夹和文件 https://stackoverflow.com/questions/48189243/create-folder-and-file-on-current-user-profile-from-admin-profile/48196886#48196886。通常不清楚如何引用计数多次部署的文件(每个用户一次)。
- 我多次重复这个建议,但有时处理用户配置文件部署确实是一场噩梦。非常常见的问题:(1)意外的数据覆盖/重置,(2)无法将用户配置文件复制到位,(3)意外卸载修改的文件(读取:用户数据),(4)无法可靠地覆盖现有文件 - 相同的问题倾向于重复。
- 当然,也可能出于其他原因需要这样的顶级文件夹,但我敢打赌,它将填充用户数据或用户可修改的文件。这准确吗?