Harvesting files with Wix Heat

If you are creating a new WiX Installer, files have to be added into installer that will be installed on user system. There are various way to add those files into WiX. If your project is evolving and you need to deploy installers constantly, it’s better to use WiX file harvester. The idea is that it takes all files needed for installer automatically, and packs it to WiX file that can be later included in WiX installer project.

We are going to write installer for my simple project, ConfigurationUtility. This tutorial is not for complete beginners, so you should have little experience with WiX.

  1. Create new WiXProject(in Visual Studio 2010 or 2012, doesn’t matter – make sure you install >=Wix3.6 before)
  2. In your WiXProject, add reference to ConfigurationUtility project. This step is needed to have make installer little less error-prone(avoids some hardcoding).
  3. Go to your WiXProject and add pre-build events(right click on project -> properties -> Build Events), and add this:
    heat dir "$(SolutionDir)ConfigurationUtility\bin\$(Configuration)" 
    			-dr ConfigurationUtilityDir 
    			-cg ConfigurationUtilityComponents 
    			-gg -g1 -sf -srd 
    			-var "var.ConfigurationUtility.TargetDir" 
    			-out "$(SolutionDir)WiXProject\ConfigurationUtilityHeat.wxs"

    Note; If you are wondering about flags, go check out heat documentation.

  4. ConfigurationUtilityHeat.wxs will be generated once you build your WiXProject. Add ConfigurationUtilityHeat.wxs into your WiXProject(“Add existing item” in VS).
  5. Now it’s time to edit your Product.wxs and pull in the “ConfigurationUtilityHeat.wxs” file. Open Product.wxs, and add:
    <!-- Add ComponentGroupRef to existing Feature, or create new one -->
    <!-- Notice the IDs & what we used in heat -->
    <Feature Id="ProductFeature" Title="Main product" Level="1">
       <ComponentGroupRef Id="ConfigurationUtilityComponents"/>
        <Directory Id="INSTALLDIR" Name="SourceDir">
          <Directory Id="ProgramFilesFolder">
            <Directory Id="ConfigurationUtilityDir" Name="ConfigurationUtility" />


And.. that’s it! The idea of harvesting is that every time we build our WiXProject, it will harvest ALL the files in concrete folder, and spit out ConfigurationUtilityHeat.wxs file, that can later be included. WiX does also offer project harvesting, which sounds very cool – until you find out that it doesn’t harvest the references of a project. That’s basically useless in my opinion. I do believe they are working for a fix, and it’s pretty complicated problem.

  • Michael McMahon

    This is exactly how I am harvesting the files for the projects I am working with. Much easier to grab them from the Bin directory since the files to be harvested are all there as opposed to harvest the project and a separate Dependency directory where all of the dependencies for all of the projects could be kept and harvested as a directory.

    This works great when building from Visual Studio. Problem I am now encountering is I want to build the solution projects and WiX projects using Team Build with a build definition. I could check the Bin directory into source control, but that has to be checked out by each developer locally so they can build the solution, this is not ideal. Team build puts those files in the root of the drop folder not a bin directory, so I get an error that the directory is empty. Actually, it doesn’t even exist.

    What is the best method for harvesting a bin directory using Team Build on a build server?

    Michael McMahon

    • chriseelmaa

      Hey Michael, I am little late to the party, however just in case you have not found the answer already, or anyone else looking for the solution.

      This is the exact same problem I stumbled upon few days ago. The easiest option is to modify your build option and let the TFS build server know that you indeed want the same “structure” as the Visual Studio provides(eg each project has its separate folder).

      You need to pass following flags to msbuild: /p:BuildProjectReferences=true /p:GenerateProjectSpecificOutputFolder=true

      Note, I also had some nasty bug where WiX did not build dependencies in correct order. I tried to find a solution, but could not find one. There’s a “hack” which will make it work though, if you ever stumble to this problem. Just pass /m:1 to msbuild. It’ll disable parallel build.

  • T K

    Thanks for the great post!

    I used to create a wxs file like this:
    “C:\Program Files\Windows Installer XML v3.5\bin\heat.exe” file MyAddin.dll -ag -template fragment -out MyAddin.wxs

    However, the result is for a per user installer – the registry entries and the class are configured to HKCU.
    How should I change the command above so that it the file contains content for a ‘per machine’ installer?

    Thanks in advance!

    • chriseelmaa


      there is no “quick fix”,

      you need to do using XSL transformations, namely pass your XSLT file and use -t switch. To see one example using it, you can take look at my other post:

  • Andrew


    I was just wondering how you would handle a subdirectory of a predefined variable?

    so for your example “-var “var.ConfigurationUtility.TargetDir” How can I make “-var “var.ConfigurationUtility.TargetDir\MyDirectory” This is because the only directory that I want to harvest is “MyDirectory” in TargetDir. Is there a way to set up this variable with candle perhaps? I’ve tried reading but have had a tough time finding a good answer.

  • Michal

    Thanks, I needed something exactly like this.
    One question, did you find any way, to change “SourceDir” prefix using another way than variable? (-var “var.ConfigurationUtility.TargetDir”). It is quite strange, that we can’t use string directly. That way it would be possible use same defined value, in prebuild event, for dir and -var directive, when source folder is not Visual Studio Solution.

  • Matthew Bordas

    This isn’t working for me in Visual Studio 2017 🙁
    I keep getting an error, “Command exited with code 9009….The ‘-out’ or ‘-o’ parameter must specify a file path.”

    I modified the build event to be the following:
    “$(WiX)bin\heat.exe” dir “$(SolutionDir)DesktopAppInstaller\bin\$(Configuration)”
    -dr DesktopAppInstaller
    -cg ProductComponents
    -ag -g1 -sfrag -srd
    -var “var.DesktopAppInstaller.TargetDir”
    -out “$(SolutionDir)DesktopAppInstaller\Files.wxs”

    My solution is composed of the DesktopAppInstaller project and the DesktopApp project.

    Any help would be greatly appreciated.

    • Matthew Bordas

      I fixed it, I didn’t realize pre-build events had to be on one line! I just deleted the newlines

  • Martin

    This is what I was looking for.
    But there are two things I would like to know.

    1. Will the generated GUIDs change every time I build the solution?
    If that’s the case, the providing of updates/upgrades with the installer would be impossible, if I am not wrong.

    2. What’s the meaning of the parameter -sf?
    I can not find this one in the documentation. Do you mean -sfrag instead?


Your email addres will not be published. All fields are required.