Search code examples
wixheatwix3.8

How can I use bind.FileVersion when harvesting using Heat?


I've previously used...

<?define PRODUCTVERSION="!(bind.FileVersion.MyLibrary.dll)" ?>

... to define a version variable for use in my installers. For the first time I'm using Heat.exe to harvest the files/folders I need in my installer (which includes MyLibrary.dll) to a file called Source.wxs.

If I try to build the installer I get the following error:

Unresolved bind-time variable !(bind.FileVersion.MyLibrary.dll)

It's like the Product.wxs file where the PRODUCTVERSION is declared can't see the Source.wxs file that has the details of the MyLibrary.dll, but I know this isn't true since if I set PRODUCTVERSION="1.0.0.0" then the installer builds and all this files are installed correctly.

How can I get bind.FileVersion to 'see' MyLibrary.dll?

EDIT

I can get it to work if I use the non-human friendly File Id from Source.wxs (see below), but is this really the best solution?

  <?define PRODUCTVERSION="!(bind.fileVersion.fil023E197261ED7268770DDE64994C4A55)" ?>

Solution

  • You can edit the output generated by Heat using XSL. That way you can transform the ID fil023E197261ED7268770DDE64994C4A55 into something more readable which can be referenced in your project. To apply a transform to a HeatDirectory task you have to specify its Transforms attribute and set its value to a file name of an XSL file you have to create.

    In that XSL file you'll have to manipulate the XML generated by heat. To rename the Id Attribute of the File element you can use the following code:

    <?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: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:copy>
      </xsl:template>
    </xsl:stylesheet>
    

    Read about XSL at w3schools and check out the documentation of the HeatDirectory task.