Wix:如何用XSLT阻止卸载时删除指定目录
解决MSI卸载/升级时保留整个Documents目录的问题
这个场景我太熟悉了——直接给Directory元素加NeverOverwrite和Permanent属性确实行不通,因为MSI的这两个属性本质上是绑定到File元素的,目录本身并不被MSI的安装引擎直接跟踪管理。下面给你几个靠谱的解决方案:
方案1:修改XSLT匹配Documents目录下的所有文件
核心思路是找到属于Documents目录的所有File元素,给它们逐一添加NeverOverwrite="yes"和Permanent="yes"属性。因为MSI只会删除它自己跟踪的文件,只要标记了这些属性,卸载时就会保留文件,升级时也不会覆盖。
示例XSLT代码:
<!-- 先获取Documents目录的唯一ID --> <xsl:variable name="documentsDirId" select="*[local-name()='Directory'][@Name='Documents']/@Id" /> <!-- 匹配所有隶属于该目录的File元素 --> <xsl:if test="*[local-name()='File']/@Directory=$documentsDirId"> <xsl:attribute name="NeverOverwrite">yes</xsl:attribute> <xsl:attribute name="Permanent">yes</xsl:attribute> </xsl:if>
如果Documents目录下还有子目录,你可以把匹配条件改成更宽泛的形式(前提是目录ID命名包含"Documents",比如INSTALLDIR_Documents_SubDir):
<xsl:if test="contains(*[local-name()='File']/@Directory, 'Documents')"> <xsl:attribute name="NeverOverwrite">yes</xsl:attribute> <xsl:attribute name="Permanent">yes</xsl:attribute> </xsl:if>
方案2:调整组件结构(适合WiX等构建工具)
如果你是用WiX构建MSI,可以把Documents目录下的所有文件单独放到一个组件里,然后给这个组件设置Permanent="yes"和NeverOverwrite="yes"属性。不过你提到这些文件是打包形式而非独立组件,这个方案可能不太适用,但可以作为备选思路。
注意事项
- 确保你的XSLT是在正确的阶段应用:比如用WiX的heat工具生成文件列表时,要把这个XSLT作为转换参数传入,才能正确修改生成的WXS文件中的File元素。
Permanent="yes"会让文件在完全卸载时也保留,如果你只是想在升级时保留、卸载时删除,可以只设置NeverOverwrite="yes",去掉Permanent属性。
内容的提问来源于stack exchange,提问作者Sjharrison
相关产品推荐
相关产品推荐

