wixwix3.6data-harvest

How to put a variable base on your build version in DefineConstants for a Harvest with HeatDirectory?


I need to harvest a directory on wix toolset, but this directory will have for name the build version number. I know how to define a static constant, but is it possible to make a variable one?

I searched on forums, but never found a harvest based on an external variable.

<PropertyGroup>
  <DefineConstants>BasePath=..\Files\$(build);</DefineConstants>
</PropertyGroup>

<HeatDirectory 
OutputFile="HarvestedCopyFiles.wxs" 
DirectoryRefId="INSTALLFOLDER" 
ComponentGroupName="HarvestedCopyFilesComponent" 
SuppressCom="true" 
Directory="..\Files" 
SuppressFragments="true" 
SuppressRegistry="true" 
SuppressRootDirectory="true" 
AutoGenerateGuids="false" 
GenerateGuidsNow="true" 
ToolPath="$(WixToolPath)" 
PreprocessorVariable="var.BasePath" />

What can I do to have this kind of $(build) variable working? Is there a way to link it to my variable.wxi file where I got : <?define ProjectBuild = "421" ?>?


Solution

  • You can do something like this by adding the BeforeBuild target to your wixproj file:

    <Target Name="BeforeBuild">
        <ItemGroup>
            <FileThatExists Include="..\Files\**\FileThatExists.txt"/>
        </ItemGroup>
    
        <PropertyGroup>
            <Build>@(FileThatExists->'%(RecursiveDir)')</Build>
            <BasePath>..\Files\$(Build)\</BasePath>
            <DefineConstants>
                $(DefineConstants);
                Build=$(Build);
                BasePath=$(BasePath);
            </DefineConstants>    
        </PropertyGroup>
    
        <HeatDirectory 
            OutputFile="HarvestedCopyFiles.wxs" 
            DirectoryRefId="INSTALLFOLDER" 
            ComponentGroupName="HarvestedCopyFilesComponent" 
            SuppressCom="true" 
            Directory="$(BasePath)" 
            SuppressFragments="true" 
            SuppressRegistry="true" 
            SuppressRootDirectory="true" 
            AutoGenerateGuids="false" 
            GenerateGuidsNow="true" 
            ToolPath="$(WixToolPath)" 
            PreprocessorVariable="var.BasePath" 
        />
    </Target>
    

    What this does is it will figure out the # of the build folder by clever use of ItemGroup metadata properties. You could alternatively make another target to get that folder name and you should be able to find some examples on SO.

    We set the Build property value to the RecursiveDir metadata of the item we made and then also define the BasePath value.

    Next we're updating the values contained in the DefineConstants property. This is the property that will let you pass in variable key value pairs to the Candle wix compiler which lets you use syntax like $(var.Build) and $(var.BasePath) in your installer source code.

    Finally we call the HeatDirectory task which will harvest your build# folder and generate the HarvestedCopyFiles.wxs file.

    I would like to suggest defining the item "HarvestDirectory" which gets used by the HarvestDirectory target which will run if one or more HarvestDirectory items exist.

    to do that you would just replace the <HeatDirectory> with

        <PropertyGroup>
            <HarvestDirectoryAutogenerateGuids>true</HarvestDirectoryAutogenerateGuids>
            <HarvestDirectoryGenerateGuidsNow>true</HarvestDirectoryGenerateGuidsNow>
        </PropertyGroup>
        <ItemGroup>
            <HarvestDirectory Include="$(BasePath)">
                DirectoryRefId="INSTALLFOLDER" 
                ComponentGroupName="HarvestedCopyFilesComponent"  
                PreprocessorVariable="var.BasePath"
                SuppressCom="true"
                SuppressRegistry="true"
                SuppressRootDirectory="true"
            </HarvestDirectory>
        </ItemGroup>
    

    I like this method better because it automatically includes the generated file in your compile sources so you don't have to include a non-existant file in your project.