我正在使用WiX加热命令(在命令行上,而不是MSBuild)为多个目录生成.wxs文件。有许多单独的目录需要收集,所以我想按原样使用生成的.wxs文件。
我的发布/构建和安装的目录结构相同,如下所示:
AppName\Mods\SomeModule
AppName\Mods\SomeOtherModule
...
AppName\Mods\YetAnotherModule
AppName\Mods\ModuleNumber42
每个目录对应一个我希望能够单独添加或省略的模块化部分,因此我不想将整个Mods目录收集到单个.wxs文件中。
目录的名称很重要;他们需要从build文件夹到install文件夹保持不变。我一直在使用这样的热量:
heat dir Mods\SomeModule -cg SomeModule -dr MyModsDir -out SomeModule.wxs
我想为每个模块目录执行此操作,然后在主文件的Feature中为每个ComponentGroup包含ComponentGroupRef。
问题是当heat生成.wxs文件时,它会在每个文件的Source中省略正在收集的目录的名称。它看起来像这样:
<DirectoryRef Id="MyModsDir">
<Directory Id="xxx" Name="SomeModule">
<Component Id="xxx" Guid="{someuuid}">
<File Id="xxx" KeyPath="yes" Source="SourceDir\file1" />
</Component>
...
</Directory>
</DirectoryRef>
当需要看起来像这样:
<DirectoryRef Id="MyModsDir">
<Directory Id="xxx" Name="SomeModule">
<Component Id="xxx" Guid="{someuuid}">
<File Id="xxx" KeyPath="yes" Source="SourceDir\SomeModule\file1" />
</Component>
...
</Directory>
</DirectoryRef>
尽我所能,我似乎无法说服热量将收获目录的名称包含在文件的Source属性中。
我仔细阅读了WiX文档并使用-var和-srd这样的选项,甚至从不同的目录运行命令,但没有成功。我已经看了一些可能的解决方案,但这些都不适合我:
我可以使用我的Mods源目录的路径定义WixVariable,然后传入,例如-var wix.ModsDir
。但是,然后WiX会直接在Mods目录中查找实际位置较深的文件。我可以为每个模块定义一个WixVariable,但是如果用如此多的变量来混淆我的命名空间似乎很愚蠢和危险。
如果我使用预处理器变量,我需要手动为每个生成的文件添加<?include?>
和/或<?define?>
行,以将模块名称附加到路径中。正如我所说的那样,我不想这样做 - 劳动密集型,容易出错,而这应该很容易通过加热自动化。
我可以为我的Mods目录添加-b选项,但后来我遇到了与上面相同的问题,其中WiX看起来不够深,无法找到文件。
或者,我必须为每个模块添加-b选项,模块目录通常包含与其他模块文件同名的文件,因此会出现名称冲突。
包含已获取目录的名称是如此简单明了的事情,我认为默认情况下会加热。我是WiX的新手,所以也许我只是误解了一些东西。关于解决这个问题的任何想法?
答案 0 :(得分:1)
通常你会使用-var var.ModNameDir。我使用HarvestDirectory目标执行类似的操作,并将DefineConstants属性更新为<DefineConstants>ModNameDir=$(ModNameDir);$(DefineConstants)</DefineConstants>
,其中$(ModNameDir)是指向文件夹路径的msbuild属性。
如果你不知道你在做什么关于msbuild,这有点令人困惑,所以,你可以使用的第三个选项就是这样一个简单的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="http://schemas.microsoft.com/wix/2006/wi"
exclude-result-prefixes="xsl wix">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- Get the right sourceDir for the files -->
<xsl:template match="wix:File/@Source">
<xsl:attribute name="{name()}">
<xsl:variable name="sourceDirStart" select="substring-before(., '\')"/>
<xsl:variable name="sourceDirEnd" select="substring-after(., '\')" />
<xsl:value-of select="concat($sourceDirStart, '\SomeModule\', $sourceDirEnd)" />
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
这应该将您的SourceDir\file1
分成SourceDir
和file1
,然后将其与\SomeModule\
连接在一起,使其变为SourceDir\SomeModule\file1
。< / p>
我不是非常精通xslt,但看起来这应该做你想要的。不幸的是,heat.exe使用xslt的1.0版本,所以你无法访问漂亮的replace
函数,而是必须以这种笨拙的方式去做。您还必须为每个Mod定义一个新的xslt文件,并通过使用-t
为文件提供热量来应用转换。
如果你想要,你可以通过用'SourceDir \'替换substring-after的'\'部分,然后删除第一个sourceDirStart,然后只删除SourceDir\
来省略concat('expected path', $sourceDirEnd)
}