如何在WiX工具集自动收割文件中配置CompanionFile属性?
解决WiX自动收割场景下System.IO.Compression.Native.dll的版本降级问题
问题背景
在.NET 6到.NET 7的MSI升级流程中,System.IO.Compression.Native.dll会出现丢失问题,核心原因是版本冲突导致安装程序未正确处理该文件的升级逻辑。官方解决方案是通过WiX的CompanionFile特性,将System.IO.Compression.dll设为Native DLL的伴生文件,让安装程序将两者视为同一组件进行版本管理。但如果使用WiX的自动收割(Heat)功能,无法直接编辑自动生成的XML元素添加该属性。
针对自动收割场景的解决方案
1. 通过XSLT转换修改收割输出(推荐)
WiX的Heat工具支持通过XSLT规则修改自动生成的WXS文件,你可以编写转换逻辑为指定文件添加CompanionFile属性。
步骤1:编写XSLT转换文件
创建AddCompanionFile.xslt,内容如下:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:wix="http://schemas.microsoft.com/wix/2006/wi"> <xsl:output method="xml" indent="yes" /> <!-- 保留所有原有元素和属性 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()" /> </xsl:copy> </xsl:template> <!-- 为System.IO.Compression.Native.dll添加CompanionFile属性 --> <xsl:template match="wix:File[contains(@Source, 'System.IO.Compression.Native.dll')]"> <xsl:copy> <xsl:apply-templates select="@*" /> <xsl:attribute name="CompanionFile">System_IO_Compression_dll</xsl:attribute> </xsl:copy> </xsl:template> <!-- 将System.IO.Compression.dll设为组件的KeyPath --> <xsl:template match="wix:File[contains(@Source, 'System.IO.Compression.dll')]"> <xsl:copy> <xsl:apply-templates select="@*" /> <xsl:attribute name="KeyPath">yes</xsl:attribute> </xsl:copy> </xsl:template> </xsl:stylesheet>
步骤2:在.wixproj中配置收割时应用转换
在项目文件的HarvestDirectory任务中添加Transform属性,指定XSLT文件路径:
<HarvestDirectory Include="$(PublishDir)"> <ComponentGroupName>AppComponents</ComponentGroupName> <DirectoryRefId>INSTALLFOLDER</DirectoryRefId> <Transform>AddCompanionFile.xslt</Transform> <SuppressCom>true</SuppressCom> <SuppressRegistry>true</SuppressRegistry> <SuppressRootDirectory>true</SuppressRootDirectory> </HarvestDirectory>
如果直接使用Heat命令行,添加-transform AddCompanionFile.xslt参数即可。
2. 自定义MSBuild目标修改收割后的WXS文件
如果XSLT无法满足需求,可以在MSBuild流程中添加自定义目标,在收割完成后直接修改生成的WXS文件:
<Target Name="PostHarvest" AfterTargets="HarvestDirectory"> <XmlPoke XmlInputPath="$(IntermediateOutputPath)\AppComponents.wxs" Query="//wix:File[contains(@Source, 'System.IO.Compression.Native.dll')]/@CompanionFile" Value="System_IO_Compression_dll" Namespaces="<Namespace Prefix='wix' Uri='http://schemas.microsoft.com/wix/2006/wi' />" /> <XmlPoke XmlInputPath="$(IntermediateOutputPath)\AppComponents.wxs" Query="//wix:File[contains(@Source, 'System.IO.Compression.dll')]/@KeyPath" Value="yes" Namespaces="<Namespace Prefix='wix' Uri='http://schemas.microsoft.com/wix/2006/wi' />" /> </Target>
该目标会在收割完成后,自动为指定文件添加所需属性。
最终效果
通过上述方法,收割生成的组件会自动调整为如下结构:
<Component Id="Comp_Compression" Guid="*"> <File Id="System_IO_Compression_dll" Source="path/to/System.IO.Compression.dll" KeyPath="yes" /> <File Id="System_IO_Compression_Native_dll" Source="path/to/System.IO.Compression.Native.dll" CompanionFile="System_IO_Compression_dll" /> </Component>
内容的提问来源于stack exchange,提问作者Kristoffer Tungland
相关产品推荐
相关产品推荐

