
Using the heat.exe tool to generate components
Sometimes, your software is going to require a lot of files: there's the main executable, supporting libraries, images, configuration files, help documentation, and potentially more. You might start out writing the Component
elements by hand, but pretty soon it's going to amount to more than you'd care to take on.
The WiX team has provided a tool called Heat to shoulder the burden. You can take this utility and point it at a directory of files, and it will generate the WiX markup for you. In this recipe, we'll try it out by creating a directory of text files and then run Heat to turn it into a .wxs
file. Heat is included in the WiX toolset.
Getting ready
To prepare for this recipe, perform the following steps:
- On your desktop, create a folder named
SourceFiles
. - Add three text files to it and name them
Sample1.txt
,Sample2.txt
, andSample3.txt
.
How to do it…
Call heat.exe
from the command line to convert a folder of files into the WiX markup using the following steps:
- Open a command prompt and change the directory to your
Desktop
folder:cd Desktop
- Invoke
heat.exe
on the folder with the following command:"%WIX%bin\heat.exe" dir "SourceFiles" -cg MyComponentGroup -dr INSTALLFOLDER -gg -sfrag -srd -var var.SourceFilesDir -out "Components.wxs"
- Check that a file called
Components.wxs
was created on your desktop. Create a new WiX setup project and copy theComponents.wxs
file into it. You can do this by dragging the file onto the Visual Studio Solution Explorer. - Define a preprocessor variable called
SourceFilesDir
as the path to theDesktop\SourceFiles
folder by opening your setup project's properties and selecting the Build tab. Then, addSourceFilesDir=C:\Users\Nick\Desktop\SourceFiles
to the textbox that's labeled Define preprocessor variables. You can also use a relative path. Use the path to your own Desktop. - To reference our new components in the project, add a
ComponentGroupRef
element to our project'sProduct.wxs
file. Its ID should match the ID ofComponentGroup
that Heat generated for us in theComponents.wxs
file:<Feature Id="ProductFeature" Title="HeatInstaller" Level="1"> <ComponentGroupRef Id="ProductComponents" /> <ComponentGroupRef Id="MyComponentGroup"/> </Feature>
How it works…
Our call to Heat began with the dir
harvest type. The term harvest
means to generate WiX markup from a source. There are several things that can be harvested, including Visual Studio projects, single standalone files and, in this case, a whole directory; hence, the dir
harvest type is used. Immediately following the harvest type is the directory where the source files can be found. In this case, we named the folder SourceFiles
.
The -cg
flag instructs heat.exe
to create a ComponentGroup
element and the Id
to assign to it; in this case, we used MyComponentGroup
. All the components that Heat generates will be included in this group.
Next, we set the -dr
flag to INSTALLFOLDER
so that our components can be installed to that directory. The -gg
flag generates GUIDs for the components. The -sfrag
flag causes all the components to be put into a single Fragment
tag, rather than having each in its own Fragment
tag. The -srd
flag tells Heat to not create a Directory
element with the name SourceFiles
, which it would have done otherwise.
The -var
flag causes each File
element to have a Source
attribute prefixed with a preprocessor variable of our choice. Here's an example of a File
element that would be generated that is prefixed with the SourceFilesDir
variable that we specified:
<File Id="filB6C392508320F3B45A8928D279282132" KeyPath="yes" Source="$(var.SourceFilesDir)\Sample2.txt" />
Having this variable in place allows us to specify the path to our text files dynamically by setting its value in the WiX setup project's properties. The last flag we used was -out
, which gives a name to the .wxs
file that Heat generates.
We copied the Components.wxs
file to a setup project and defined the SourceFilesDir
preprocessor variable so that it pointed to the folder on our desktop. The reason that we need to do this is that the .wxs
file only contains markup to add the files. The actual source files themselves must still be linked-in during compilation. Finally, we added a ComponentGroupRef
element within our Feature
so that the new components would be included in the MSI.
There's more…
In this recipe, we did all of our work from the command line. We can do the same job within a setup project's .wixproj
file using the MSBuild syntax. That way, the latest files will be pulled in each time we build the project. The key is to use the HeatDirectory
task.
Here's an example where we've added a HeatDirectory
task inside of the BeforeBuild
target in our .wixproj
file:
<Target Name="BeforeBuild"> <PropertyGroup> <WixToolPath>C:\Program Files (x86)\WiX Toolset v3.8\bin\</WixToolPath> </PropertyGroup> <HeatDirectory ToolPath="$(WixToolPath)" Directory="$(ProjectDir)SourceFiles" ComponentGroupName="MyComponentGroup" DirectoryRefId="INSTALLFOLDER" GenerateGuidsNow="true" SuppressFragments="true" SuppressRootDirectory="true" PreprocessorVariable="var.SourceFilesDir" OutputFile="Components.wxs" /> </Target>
As before, the SourceFilesDir
preprocessor variable would need to be defined in the project's properties and MyComponentGroup
should be added as ComponentGroupRef
within the feature. Also, we will need to add the Component.wxs
file to the project after the first time that it's generated. From then on, it will be automatically updated for you each time you build the project.
More information about the HeatDirectory
task can be found at http://wixtoolset.org/documentation/manual/v3/msbuild/task_reference/heatdirectory.html.