我正在使用WiX 3.8来构建一个安装产品的项目。安装程序基本完成。由软件包安装的程序之一是依赖于第三方的dll,它经常更新。特别是dll的版本号定期更改。在第一次编写安装程序项目时,我没有考虑支持更改文件名并手动编写每个组件。
将来应该更改此行为。如果我理解正确,可以在HeatDirectory Task的帮助下自动生成文件组件。我现在使用HeatDirectory Task创建了一个示例项目。但是HeatDirectory Task产生的输出与我过去使用的手动编写的组件之间存在一些差异。
我希望HeatDirectory Task尽可能好地生成与我的手动方法相同的输出。以下是两个组件的代码,首先手动创建,然后由HeatDirectory任务创建:
手动创建的组件:
<ComponentGroup Id="ThirdParty.v13.2" Directory="INSTALLFOLDER">
<Component
Id="CMP_ThirdParty.v13.2.dll"
Guid="AC5E00F0-B458-4272-B132-F13594ED4916">
<File
Id="ThirdParty.v13.2.dll"
Name="ThirdParty.v13.2.dll"
Source="ComponentsDir\ThirdParty\ThirdParty.v13.2.dll"
KeyPath="yes"
Assembly=".net"
AssemblyApplication="ThirdParty.v13.2.dll"
AssemblyManifest="ThirdParty.v13.2.dll"
Compressed="no"
DiskId="$(var.ThirdPartyDiskId)"/>
</Component>
<Component
Id="CMP_ThirdParty.v13.2.xml"
Guid="64AC3F5F-38E9-41EC-B714-636F5D9C0CB4">
<File
Id="ThirdParty.v13.2.xml"
Name="ThirdParty.v13.2.xml"
Source="Source="ComponentsDir\ThirdParty\ThirdParty.v13.2.xml"
KeyPath="yes"
Compressed="no"
DiskId="$(var.ThirdPartyDiskId)"/>
</Component>
</ComponentGroup>
HeatDirectory任务生成代码:
<ComponentGroup Id="Files">
<Component
Id="cmp9D064A733360960E07277CFD9AB84AF1"
Directory="INSTALLFOLDER"
Guid="*">
<File
Id="filD5DCB6E091D2D12303E2E80B0B767438"
KeyPath="yes"
Source="$(var.Path)\ThirdParty.v13.2.dll"/>
</Component>
<Component
Id="cmpA8681A63A8A4991D18824BA17E4CA4BF"
Directory="INSTALLFOLDER"
Guid="*">
<File
Id="fil17554B3CD0E576337AEC758831009938"
KeyPath="yes"
Source="$(var.Path)\ThirdParty.v13.2.xml"/>
</Component>
</ComponentGroup>
产生上述输出的代码如下:
<Target Name="BeforeBuild">
<HeatDirectory
DirectoryRefId="INSTALLFOLDER"
OutputFile="Files.wxs"
Directory="S:\omePath"
SuppressRootDirectory="true"
ToolPath="$(WixToolPath)"
AutogenerateGuids="true"
ComponentGroupName="Files"
PreprocessorVariable="var.Path">
</HeatDirectory>
</Target>
我现在要记下我想改变的HeatDirectory任务生成代码的特性:
Directory
属性。我希望父ComponentGroup
拥有Directory
属性,并在每个子组件中省略它。Id
属性由前缀CMP
后跟文件名组成。据我所知,项目中不能有两个文件名相同的文件,但我知道情况并非如此。我不想要任务生成的神秘标识符。File
子项太过于简单。我希望HeatDirectoy Task为每个文件创建一个Name
属性,该文件是文件的当前名称。然后,Compressed
属性应添加值no
,DiksId
应添加变量值,可以在某种程度上在任务中指定。Asssembly
附加值.net
,AssemblyApplication
,并将已获取文件的名称作为其值&amp; AssemblyManifest
也将已获取文件的名称作为其值。是否可以通过HeatDirectory任务实现这一目标?
答案 0 :(得分:1)
操纵HeatDirectory任务输出的答案是使用XSLT。在HeatDirectory任务中,可以指定一个名为Transforms
的属性,该属性指向包含XSLT指令的文件。为了实现我要求的输出,可以使用以下XSLT代码:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:wix="http://schemas.microsoft.com/wix/2006/wi"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl">
<xsl:output
method="xml"
indent="yes"/>
<xsl:variable name="ComponentGroup-Id" select="//wix:ComponentGroup/@Id"/>
<xsl:variable name="DestinationFolder" select="//wix:Component[1]/@Directory"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select ="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//wix:Directory">
<xsl:variable name="DirName" select="@Name" />
<xsl:copy>
<xsl:attribute name="Id">
<xsl:value-of select="$ComponentGroup-Id"/>
<xsl:text>_</xsl:text>
<xsl:value-of select="$DirName"/>
</xsl:attribute>
<xsl:attribute name="Name">
<xsl:value-of select="$DirName"/>
</xsl:attribute>
</xsl:copy>
</xsl:template>
<xsl:template match="//wix:ComponentGroup">
<xsl:copy>
<xsl:attribute name="Id">
<xsl:value-of select="$ComponentGroup-Id"/>
</xsl:attribute>
<xsl:attribute name="Directory">
<xsl:value-of select="$DestinationFolder"/>
</xsl:attribute>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="//wix:Component">
<xsl:variable name="FilePath" select="current()/wix:File/@Source" />
<xsl:variable name="FileName" select="substring-after($FilePath,'\')" />
<xsl:variable name="Guid" select="@Guid" />
<xsl:copy>
<xsl:attribute name="Id">
<xsl:text>CMP_</xsl:text>
<xsl:choose>
<xsl:when test="contains($FileName,'\')">
<xsl:value-of select="substring-after($FileName,'\')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$FileName"/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:attribute name="Guid">
<xsl:value-of select="$Guid"/>
</xsl:attribute>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="//wix:File">
<xsl:variable name="FilePath" select="@Source" />
<xsl:variable name="FileName" select="substring-after($FilePath,'\')" />
<xsl:copy>
<xsl:attribute name="Id">
<xsl:choose>
<xsl:when test="contains($FileName,'\')">
<xsl:value-of select="substring-after($FileName,'\')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$FileName"/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:attribute name="KeyPath">
<xsl:text>yes</xsl:text>
</xsl:attribute>
<xsl:attribute name="Source">
<xsl:value-of select="$FilePath"/>
</xsl:attribute>
<xsl:if test="contains($FileName,'.dll')">
<xsl:attribute name="Assembly">.net</xsl:attribute>
<xsl:attribute name="AssemblyApplication">
<xsl:choose>
<xsl:when test="contains($FileName,'\')">
<xsl:value-of select="substring-after($FileName,'\')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$FileName"/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:attribute name="AssemblyManifest">
<xsl:choose>
<xsl:when test="contains($FileName,'\')">
<xsl:value-of select="substring-after($FileName,'\')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$FileName"/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:if>
<xsl:attribute name="Compressed">
<xsl:text>no</xsl:text>
</xsl:attribute>
<xsl:attribute name="DiskId">
<xsl:text>$(var.SomeDiskID)</xsl:text>
</xsl:attribute>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>