[wix-users] automated fileset using heat

Phill Hogland phill.hogland at rimage.com
Thu Feb 11 08:12:36 PST 2016


We have scripts in our C++ Build process that moves the output files to a file server structured to reflect how the files would be laid out on a target system.
ProductALargeSuite\Model\programfiles\<folder tree under programfiles as created on a target system>    
ProductALargeSuite\Model\STATIC\programfile\<folder tree under programfiles as created on a target system>    These are files, possibly icon files, config files, etc that are not created in the build process.

Then in my projects I use HarvestDirectory to harvest the folder tree (or some portion of it for a particular app) by adding a Harvest.tragets file, like this:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <!-- cut and paste property names from wix2010.targets - spelling errors bite!-->
    <HarvestNoLogo>true</HarvestNoLogo>
    <HarvestVerboseOutput>true</HarvestVerboseOutput>
    <HarvestAutogenerateGuids>true</HarvestAutogenerateGuids>
    <HarvestSupressFragments>false</HarvestSupressFragments>
    <HarvestSuppressUniqueIds>true</HarvestSuppressUniqueIds>
  </PropertyGroup>
  <ItemGroup>
    <HarvestDirectory Include="\\server\drive\path-to_product_model\Model\programfiles\Company\App1">
      <DirectoryRefId> App1Dir</DirectoryRefId>
      <Transforms> App1.xslt;..\Common\Transforms\bindpath.xslt</Transforms>
      <ComponentGroupName> App1Group</ComponentGroupName>
      <PreprocessorVariable>wix.ImgServer</PreprocessorVariable>
      <KeepEmptyDirectories>false</KeepEmptyDirectories>
      <SuppressCom>true</SuppressCom>
      <SuppressRootDirectory>true</SuppressRootDirectory>
      <SuppressRegistry>true</SuppressRegistry>
      <Visible>false</Visible>
    </HarvestDirectory>
    <HarvestDirectory Include="\\server\drive\ path-to_product_model \Model\STATIC\programfiles\Company\App1">
      <DirectoryRefId> App1Dir</DirectoryRefId>
      <Transforms>..\Common\Transforms\bindpath.xslt</Transforms>
      <ComponentGroupName>STATIC_ App1Group</ComponentGroupName>
      <PreprocessorVariable>wix.STATIC_ImgServer</PreprocessorVariable>
      <KeepEmptyDirectories>false</KeepEmptyDirectories>
      <SuppressCom>true</SuppressCom>
      <SuppressRootDirectory>true</SuppressRootDirectory>
      <SuppressRegistry>true</SuppressRegistry>
      <Visible>false</Visible>
    </HarvestDirectory>
  </ItemGroup>
</Project>

My project file has this AFTER all of the 'configuration' properties are defined, and BEFORE the first ItemGroup
  <PropertyGroup>
    <CompilerAdditionalOptions>
      $(CompilerAdditionalOptions)
..... common includes
   </CompilerAdditionalOptions>
    <LinkerAdditionalOptions>
      $(LinkerAdditionalOptions)
      -nologo
      -b App1="\\server\drive\path-to-model\Model\programfiles\company\App1\\"
      -b STATIC_App1="\\ server\drive\path-to-model\\Model\STATIC\programfiles\ company\App1\\"
    </LinkerAdditionalOptions>
  </PropertyGroup>
  <Import Project="Harvest.targets" />


My bindpath.xslt is
<?xml version="1.0" encoding="utf-8"?>
<!--  Interesting Code from this post:
http://stackoverflow.com/questions/19515397/deploy-multiple-wcf-webservices-with-wix-toolset-wrong-svc-files
which I then modified by changing the search and replace, to look for '!wix.' and replace with'!(bindpath.'.
This change allows me to us %HarvestDirectory.PreprocessorVariable to specify the bindpath name.-->

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt"
        xmlns:wix="http://schemas.microsoft.com/wix/2006/wi"
        exclude-result-prefixes="msxsl">
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
    
  <!-- Always strip these files - not specifically related to binding. -->  
  <xsl:key name="thumbs.db-search" match="wix:Component[contains(wix:File/@Source, 'Thumbs.db')]" use="@Id" />
  <xsl:template match="wix:Component[key('thumbs.db-search', @Id)]" />
  <xsl:template match="wix:ComponentRef[key('thumbs.db-search', @Id)]" />

  <xsl:key name="svn-search" match="wix:Component[contains(wix:File/@Source, '*.svn')]" use="@Id" />
  <xsl:template match="wix:Component[key('svn-search', @Id)]" />
  <xsl:template match="wix:ComponentRef[key('svn-search', @Id)]" />

  <!-- Support using bindpath names. -->
  <xsl:template name="string-replace-all">
    <xsl:param name="text" />
    <xsl:param name="replace" />
    <xsl:param name="by" />
    <xsl:choose>
      <xsl:when test="contains($text, $replace)">
        <xsl:value-of select="substring-before($text,$replace)" />
        <xsl:value-of select="$by" />
        <xsl:call-template name="string-replace-all">
          <xsl:with-param name="text" select="substring-after($text,$replace)" />
          <xsl:with-param name="replace" select="$replace" />
          <xsl:with-param name="by" select="$by" />
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$text" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="@Source['!(wix.']" >

    <xsl:attribute name="Source">

      <xsl:variable name="projectName">
        <xsl:value-of select="/wix:Wix/wix:Fragment/wix:ComponentGroup/@Id"/>
      </xsl:variable>

      <xsl:call-template name="string-replace-all">
        <xsl:with-param name="text" select="." />
        <xsl:with-param name="replace" select="'!(wix.'" />
        <xsl:with-param name="by" select="'!(bindpath.'" />
      </xsl:call-template>

    </xsl:attribute>

  </xsl:template>

</xsl:stylesheet>

And in the wxs a file might be:
<File Id="file.exe.local" KeyPath="yes" Source="!(bindpath.STATIC_ImgServer)\file.exe.local" />

I have used this approach in many (100+) large and small projects it is working well for me.  By using scripts at the C++ build server to stage the files to a source server using the folder tree that is planned for the product, I have avoided the trials of using Heat project harvesting, which others have reported.  I used to launch Heat in a BeforeBuild task, but I much prefer using HarvestDirectory task as it is much simpler and more reliable.   By prestaging the files I usually only have one (or possibly two as in this example) HarvestDirectory blocks per MSI wixproj, whereas when I was building with heat.exe for one project which was not prestagged I was calling it many times to grab all of the different files from different projects, and if there was a file of the same name in two different folders, that would cause problems with the generated IDs.  Pre-staging the files and calling heat a single time for a large folder tree resolved the ID conflicts, so that is my recommendation. 

Phill

-----Original Message-----
From: wix-users [mailto:wix-users-bounces at lists.wixtoolset.org] On Behalf Of Steve Ogilvie
Sent: Thursday, February 11, 2016 9:39 AM
To: WiX User List <wix-users at lists.wixtoolset.org>
Subject: [wix-users] automated fileset using heat

Hi folks,

We are using WiX 3.10.2 and TFS 2015 with VS 2015.

Currently I use heat to harvest a large fileset, then manually put in the components/file elements into the product.wxs.

Is anyone using heat to automate the harvesting of large filesets within the build process (we use MSBUILD)

I.e. use heat the harvest a folder structure (a web application) and have heat use variables for the sourceDir and the Component Group name.
Have that Component Group listed in the feature set and etc. So the build process just runs heat before building the installer.

Success/failure/ups/downs???

Someone has suggested I try this and before I do all the work to try it want feedback from the WiX community...

Thanks,

Steve

_______________________
Steven Ogilvie

Ottawa, ON
Canada

Winston Churchill, "We make a living by what we get, but we make a life by what we give."


____________________________________________________________________
WiX Toolset Users Mailing List provided by FireGiant http://www.firegiant.com/


More information about the wix-users mailing list