使用WiX heat dir,如何在每个文件的Source中包含目录名?

时间:2018-03-22 20:57:53

标签: wix windows-installer wix3 heat

我正在使用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这样的选项,甚至从不同的目录运行命令,但没有成功。我已经看了一些可能的解决方案,但这些都不适合我:

  1. 使用-var选项加热,以便我可以传递预处理器或wix变量。
  2. 我可以使用我的Mods源目录的路径定义WixVariable,然后传入,例如-var wix.ModsDir。但是,然后WiX会直接在Mods目录中查找实际位置较深的文件。我可以为每个模块定义一个WixVariable,但是如果用如此多的变量来混淆我的命名空间似乎很愚蠢和危险。

    如果我使用预处理器变量,我需要手动为每个生成的文件添加<?include?>和/或<?define?>行,以将模块名称附加到路径中。正如我所说的那样,我不想这样做 - 劳动密集型,容易出错,而这应该很容易通过加热自动化。

    1. 使用灯时使用-b选项。
    2. 我可以为我的Mods目录添加-b选项,但后来我遇到了与上面相同的问题,其中WiX看起来不够深,无法找到文件。

      或者,我必须为每个模块添加-b选项,模块目录通常包含与其他模块文件同名的文件,因此会出现名称冲突。

      包含已获取目录的名称是如此简单明了的事情,我认为默认情况下会加热。我是WiX的新手,所以也许我只是误解了一些东西。关于解决这个问题的任何想法?

1 个答案:

答案 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分成SourceDirfile1,然后将其与\SomeModule\连接在一起,使其变为SourceDir\SomeModule\file1。< / p>

我不是非常精通xslt,但看起来这应该做你想要的。不幸的是,heat.exe使用xslt的1.0版本,所以你无法访问漂亮的replace函数,而是必须以这种笨拙的方式去做。您还必须为每个Mod定义一个新的xslt文件,并通过使用-t为文件提供热量来应用转换。

如果你想要,你可以通过用'SourceDir \'替换substring-after的'\'部分,然后删除第一个sourceDirStart,然后只删除SourceDir\来省略concat('expected path', $sourceDirEnd) }