title: Not generating required wxs output via heat and xslt for application shortcuts
body: <p>I am new to both wix and xslt. I can build an installation file using the wixedit GUI, but need to automate the process. I am using a Windows build machine.</p>
  
  <p>I am using heat to harvest all the files and do an xsl transform to try to get a result similar to what I get if I create the install package via wixedit.</p>
  
  <p>The commands used are:</p>
  
  <pre><code>%WX_HOME%\heat.exe dir "%BUILD_DEST%" -ag -gg -nologo -projectname "%PROJ%" -template product -sfrag -v -platform x86 -var var.AppSource -t %TOOLS_SRC_DIR%\heat.xsl -out %WX_WXS_FILE%
  %WX_HOME%\candle.exe -arch x86 -nologo -out %BUILD_DEST%\%PROJ%.wixobj -v %WX_WXS_FILE% -dAppSource=%BUILD_DEST% -ext WixUtilExtension
  %WX_HOME%\light.exe -nologo -out "%INSTALL_FILE%" -v %BUILD_DEST%\%PROJ%.wixobj
  </code></pre>
  
  <p>Via xslt I am adding a "file" attribute to each file entry and use it in a query to find a given application executable to add the required shortcuts.</p>
  
  <p>After much xsl trial and error and internet searching, I'm stuck. In the xsl below I've marked the 2 commented out sections with a "FIXME" and description of the problem caused by that section.</p>
  
  <p><strong>Basically, I think there are at least 2 stages of correction required: Fix the error for EXE_FILE. Then, be able to add desktop and program menu shortcuts, which includes generating the icon elements inside the product element.</strong></p>
  
  <p>Using the heat.xsl file shown below, light produces an error</p>
  
  <pre><code>LGHT0094: Unresolved reference to symbol 'Component:EXE_FILE' in section 'Product:{A0953F8D-5F10-47A4-BF70-A2B68B6399D8}'.
  </code></pre>
  
  <p>However the EXE_FILE is correctly an id attribute for the executable file in output.
  There are similar error messages for Directory:DesktopFolder, Directory:ProgramMenuDir, Icon:DesktopIcon.exe, and Icon:StartMenuIcon.exe.
  Obviously the icon ones are because the icon section is not being built at the moment.</p>
  
  <p>heat.xsl:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;xsl:stylesheet version="1.0" 
          xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
          xmlns:wix="http://schemas.microsoft.com/wix/2006/wi"
          xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"
          xmlns="http://schemas.microsoft.com/wix/2006/wi"&gt;
  
  &lt;xsl:output method="xml" indent="yes"/&gt;
  
  &lt;xsl:param name="pManufacturer" select="'Me'"/&gt;
  &lt;xsl:param name="pName" select="'MyApp'"/&gt;
  &lt;xsl:param name="pVersion" select="'0.0.0.1'"/&gt;
  &lt;xsl:param name="pPackageDesc" select="'My application'"/&gt;
  &lt;xsl:param name="pPackageComment" select="'My application'"/&gt;
  &lt;xsl:param name="pExeName" select="'4DIAC-IDE.exe'"/&gt;
  &lt;xsl:param name="pCabName" select="'MyInstall.cab'"/&gt;
  
  &lt;!-- copy all to output --&gt;
  &lt;xsl:template match="@*|*"&gt;
      &lt;xsl:copy&gt;
          &lt;xsl:apply-templates select="@*" /&gt;
          &lt;xsl:apply-templates select="*" /&gt;
      &lt;/xsl:copy&gt;
  &lt;/xsl:template&gt;
  
  &lt;!-- Ignore svn directories --&gt;
  &lt;xsl:template match="wix:Directory[@Name='.svn']" /&gt;
  &lt;!-- Create searches for the directories to remove. --&gt;
  &lt;xsl:key name="svn-search" match="wix:Directory[@Name = '.svn']" use="@Id" /&gt;
  &lt;!-- Remove components referencing those directories --&gt;
  &lt;xsl:template match="wix:Component[key('svn-search', @Directory)]" /&gt;
  
  &lt;!-- Set manufacturer attribute --&gt;
  &lt;xsl:template match="wix:Product/@Manufacturer"&gt;
      &lt;xsl:attribute name="Manufacturer"&gt;&lt;xsl:value-of select="$pManufacturer"/&gt;&lt;/xsl:attribute&gt;
  &lt;/xsl:template&gt;
  
  &lt;!-- Set product name attribute --&gt;
  &lt;xsl:template match="wix:Product/@Name"&gt;
      &lt;xsl:attribute name="Name"&gt;&lt;xsl:value-of select="$pName"/&gt;&lt;/xsl:attribute&gt;
  &lt;/xsl:template&gt;
  
  &lt;!-- Set product version attribute --&gt;
  &lt;xsl:template match="wix:Product/@Version"&gt;
      &lt;xsl:attribute name="Version"&gt;&lt;xsl:value-of select="$pVersion"/&gt;&lt;/xsl:attribute&gt;
  &lt;/xsl:template&gt;
  
  &lt;!-- Add description and comments attributes to package element --&gt;
  &lt;xsl:template match="wix:Package"&gt;
      &lt;xsl:copy&gt;
          &lt;xsl:apply-templates select="@*"/&gt;
          &lt;xsl:attribute name="Description"&gt;&lt;xsl:value-of select="$pPackageDesc"/&gt;&lt;/xsl:attribute&gt;
          &lt;xsl:attribute name="Comments"&gt;&lt;xsl:value-of select="$pPackageComment"/&gt;&lt;/xsl:attribute&gt;
          &lt;xsl:attribute name="InstallerVersion"&gt;200&lt;/xsl:attribute&gt;
          &lt;xsl:attribute name="Compressed"&gt;yes&lt;/xsl:attribute&gt;
      &lt;/xsl:copy&gt;
  &lt;/xsl:template&gt;
  
  &lt;!-- Set media element --&gt;
  &lt;xsl:template match="wix:Media"&gt;
      &lt;xsl:copy&gt;
          &lt;xsl:copy-of select="@*"/&gt;
          &lt;xsl:attribute name="Id"&gt;1&lt;/xsl:attribute&gt;
          &lt;xsl:attribute name="Cabinet"&gt;&lt;xsl:value-of select="$pCabName"/&gt;&lt;/xsl:attribute&gt;
          &lt;xsl:attribute name="EmbedCab"&gt;yes&lt;/xsl:attribute&gt;
          &lt;xsl:copy-of select="node()"/&gt;
      &lt;/xsl:copy&gt;
  &lt;/xsl:template&gt;
  
  &lt;!-- Set default feature element --&gt;
  &lt;xsl:template match="wix:Feature"&gt;
      &lt;xsl:copy&gt;
          &lt;xsl:apply-templates select="@*"/&gt;
          &lt;xsl:attribute name="Id"&gt;DefaultFeature&lt;/xsl:attribute&gt;
          &lt;xsl:attribute name="Level"&gt;1&lt;/xsl:attribute&gt;
          &lt;xsl:attribute name="Title"&gt;Main Feature&lt;/xsl:attribute&gt;
  
          &lt;!-- Set component references --&gt;
          &lt;!-- TODO is this necessary? --&gt;
          &lt;xsl:element name="ComponentRef"&gt;
              &lt;xsl:attribute name="Id"&gt;EXE_FILE&lt;/xsl:attribute&gt;
          &lt;/xsl:element&gt;
          &lt;!-- 
          &lt;xsl:element name="ComponentRef"&gt;
              &lt;xsl:attribute name="Id"&gt;StartMenuShortcuts&lt;/xsl:attribute&gt;
          &lt;/xsl:element&gt;
          --&gt;
      &lt;/xsl:copy&gt;
  &lt;/xsl:template&gt;
  
  &lt;!-- Add DesktopFolder and ProgramMenuDir --&gt;
  &lt;!-- FIXME ***********************************************************
       When this template is used, the name attribute for each file does not get added
       and therefore neither do the shortcuts.
       Refer to match File template below.
  &lt;xsl:template match="wix:Directory"&gt;
      &lt;xsl:copy&gt;
          &lt;xsl:choose&gt;
              &lt;xsl:when test="@Id='TARGETDIR'"&gt;
                  &lt;xsl:apply-templates select="@*"/&gt;
                  &lt;xsl:copy-of select="node()"/&gt;
  
                  &lt;xsl:element name="Directory"&gt;
                      &lt;xsl:attribute name="Id"&gt;DesktopFolder&lt;/xsl:attribute&gt;
                  &lt;/xsl:element&gt;
                  &lt;xsl:element name="Directory"&gt;
                      &lt;xsl:attribute name="Id"&gt;ProgramMenuDir&lt;/xsl:attribute&gt;
                      &lt;xsl:attribute name="Name"&gt;&lt;xsl:value-of select="$pManufacturer"/&gt;&lt;/xsl:attribute&gt;
                  &lt;/xsl:element&gt;
              &lt;/xsl:when&gt;
              &lt;xsl:otherwise&gt;
                  &lt;xsl:apply-templates select="@*"/&gt;
                  &lt;xsl:copy-of select="node()"/&gt;
              &lt;/xsl:otherwise&gt;
          &lt;/xsl:choose&gt;
      &lt;/xsl:copy&gt;
  &lt;/xsl:template&gt;
  --&gt;
  
  &lt;!-- Add icons to product element --&gt;
  &lt;!-- FIXME ***********************************************************
       When this template is used, the placeholder "PUT-FEATURE-TITLE-HERE" appears instead of my feature element,
       and the name attribute for each file is not output.
  &lt;xsl:template match="wix:Product"&gt;
      &lt;xsl:copy&gt;
          &lt;xsl:apply-templates select="@*"/&gt;
          &lt;xsl:copy-of select="node()"/&gt;
  
          &lt;Icon Id="DesktopIcon.exe" SourceFile="$(var.AppSource)\$pExeName" /&gt;
          &lt;Icon Id="StartMenuIcon.exe" SourceFile="$(var.AppSource)\$pExeName" /&gt;
      &lt;/xsl:copy&gt;
  &lt;/xsl:template&gt;
  --&gt;
  
  &lt;!-- Find our executable file and set shortcuts for desktop and program menu --&gt;
  &lt;!-- TODO can heat generate Name attribute? --&gt;
  &lt;xsl:template match="wix:File"&gt;
  
      &lt;!-- Get file name from Source attribute --&gt;
      &lt;xsl:variable name="fileName"&gt;
          &lt;xsl:call-template name="fileNameFromPath"&gt;
              &lt;xsl:with-param name="path" select="@Source"/&gt;
          &lt;/xsl:call-template&gt;
      &lt;/xsl:variable&gt;
  
      &lt;!-- Add Name attribute to File --&gt;
      &lt;xsl:copy&gt;
          &lt;xsl:attribute name="Name"&gt;&lt;xsl:value-of select="$fileName"/&gt;&lt;/xsl:attribute&gt;
          &lt;xsl:apply-templates select="@*"/&gt;
  
          &lt;xsl:if test="$fileName=$pExeName"&gt;
              &lt;!-- Set Id to match ComponentRef --&gt;
              &lt;xsl:attribute name="Id"&gt;EXE_FILE&lt;/xsl:attribute&gt;
              &lt;!-- Add application shortcuts --&gt;
              &lt;xsl:element name="Shortcut"&gt;
                  &lt;xsl:attribute name="Id"&gt;desktopShortcut&lt;/xsl:attribute&gt;
                  &lt;xsl:attribute name="Directory"&gt;DesktopFolder&lt;/xsl:attribute&gt;
                  &lt;xsl:attribute name="Name"&gt;&lt;xsl:value-of select="$pName"/&gt;&lt;/xsl:attribute&gt;
                  &lt;xsl:attribute name="WorkingDirectory"&gt;INSTALLDIR&lt;/xsl:attribute&gt;
                  &lt;xsl:attribute name="Advertise"&gt;yes&lt;/xsl:attribute&gt;
                  &lt;xsl:attribute name="Icon"&gt;DesktopIcon.exe&lt;/xsl:attribute&gt;
                  &lt;xsl:attribute name="IconIndex"&gt;0&lt;/xsl:attribute&gt;
              &lt;/xsl:element&gt;
              &lt;xsl:element name="Shortcut"&gt;
                  &lt;xsl:attribute name="Id"&gt;ExeShortcut&lt;/xsl:attribute&gt;
                  &lt;xsl:attribute name="Directory"&gt;ProgramMenuDir&lt;/xsl:attribute&gt;
                  &lt;xsl:attribute name="Name"&gt;&lt;xsl:value-of select="$pName"/&gt;&lt;/xsl:attribute&gt;
                  &lt;xsl:attribute name="WorkingDirectory"&gt;INSTALLDIR&lt;/xsl:attribute&gt;
                  &lt;xsl:attribute name="Advertise"&gt;yes&lt;/xsl:attribute&gt;
                  &lt;xsl:attribute name="Icon"&gt;StartMenuIcon.exe&lt;/xsl:attribute&gt;
                  &lt;xsl:attribute name="IconIndex"&gt;0&lt;/xsl:attribute&gt;
              &lt;/xsl:element&gt;
          &lt;/xsl:if&gt;
      &lt;/xsl:copy&gt;
  &lt;/xsl:template&gt;
  
  &lt;!-- template to get file name from path --&gt;
  &lt;xsl:template name="fileNameFromPath"&gt;
      &lt;xsl:param name="path" /&gt;
      &lt;xsl:choose&gt;
          &lt;xsl:when test="contains($path,'\')"&gt;
              &lt;xsl:call-template name="fileNameFromPath"&gt;
                  &lt;xsl:with-param name="path" select="substring-after($path,'\')" /&gt;
              &lt;/xsl:call-template&gt;
          &lt;/xsl:when&gt;
          &lt;xsl:when test="contains($path,'/')"&gt;
              &lt;xsl:call-template name="fileNameFromPath"&gt;
                  &lt;xsl:with-param name="path" select="substring-after($path,'/')" /&gt;
              &lt;/xsl:call-template&gt;
          &lt;/xsl:when&gt;
          &lt;xsl:otherwise&gt;
              &lt;xsl:value-of select="$path" /&gt;
          &lt;/xsl:otherwise&gt;
      &lt;/xsl:choose&gt;
  &lt;/xsl:template&gt;
  &lt;/xsl:stylesheet&gt;
  </code></pre>
  
  <p>The relevant parts of the current wxs output file are:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"&gt;
  &lt;Product Id="{A0953F8D-5F10-47A4-BF70-A2B68B6399D8}" Language="1033" Manufacturer="Me" Name="MyApp" UpgradeCode="{EAF31C16-363E-42E8-9110-4EB3ACE2CB32}" Version="0.0.0.1"&gt;
      &lt;Package Description="My application" Comments="My application" InstallerVersion="200" Compressed="yes" /&gt;
      &lt;Directory Id="TARGETDIR" Name="SourceDir"&gt;
          &lt;Directory Id="dirDE09E8843EFC6098356C132F8C772506" Name="MyBase"&gt;
              &lt;Directory Id="dirBA2DB469295E757A153AE4E941866015" Name="MyApp"&gt;
                  &lt;Component Id="cmp6F02BEBF925E45E085A43C8E9129B40A" Guid="*"&gt;
                      &lt;File Name=".eclipseproduct" Id="fil5C63854A4E335C543D7ECE7BB88B2658" KeyPath="yes" Source="$(var.AppSource)\MyApp\.eclipseproduct" /&gt;
                  &lt;/Component&gt;
                  &lt;Component Id="cmpC186B297004F1D5F5F25B295B20B89A3" Guid="*"&gt;
                      &lt;File Name="4DIAC-IDE.exe" KeyPath="yes" Source="$(var.AppSource)\MyApp\4DIAC-IDE.exe" Id="EXE_FILE"&gt;
                          &lt;Shortcut Id="desktopShortcut" Directory="DesktopFolder" Name="MyApp" WorkingDirectory="INSTALLDIR" Advertise="yes" Icon="DesktopIcon.exe" IconIndex="0" /&gt;
                          &lt;Shortcut Id="ExeShortcut" Directory="ProgramMenuDir" Name="MyApp" WorkingDirectory="INSTALLDIR" Advertise="yes" Icon="StartMenuIcon.exe" IconIndex="0" /&gt;
                      &lt;/File&gt;
                  &lt;/Component&gt;
  
                  ...
  
              &lt;/Directory&gt;
          &lt;/Directory&gt;
      &lt;/Directory&gt;
      &lt;Feature Id="DefaultFeature" Level="1" Title="Main Feature"&gt;
          &lt;ComponentRef Id="EXE_FILE" /&gt;
      &lt;/Feature&gt;
      &lt;Media Id="1" Cabinet="MyInstall.cab" EmbedCab="yes" /&gt;
  &lt;/Product&gt;
  &lt;/Wix&gt;
  </code></pre>
  
  <p>The desired/similar relevant parts generated manually via wixedit are:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"&gt;
  &lt;Product Id="6298B282-F405-4AD8-9858-649B832A2AED" Name="MyApp" Language="1033" Version="0.0.0.1" Manufacturer="Me" UpgradeCode="932EE819-799F-4A71-B0A9-7CC8128228E5"&gt;
      &lt;Package Description="My application" Comments="My application" InstallerVersion="200" Compressed="yes" /&gt;
      &lt;Media Id="1" Cabinet="MyInstall.cab" EmbedCab="yes" /&gt;
      &lt;Directory Id="TARGETDIR" Name="SourceDir"&gt;
          &lt;Directory Id="ProgramFilesFolder" Name="PFiles"&gt;
              &lt;Directory Id="Lee" Name="Lee"&gt;
                  &lt;Directory Id="MyApp" Name="MyApp"&gt;
                      &lt;Component Id="_.ECLIPSEPRODUCT" DiskId="1" Guid="AE456466-489C-4A83-BD1A-E4867B657E27"&gt;
                          &lt;File Id="_.ECLIPSEPRODUCT" Name=".eclipseproduct" Source="JenkinsCI\workspace\PC-manualPackage\Lee\MyApp\.eclipseproduct" /&gt;
                      &lt;/Component&gt;
                      &lt;Component Id="_4DIAC_IDE.EXE" DiskId="1" Guid="4E3A8845-E606-45D2-8C48-B6119B7F4D8C"&gt;
                          &lt;File Id="_4DIAC_IDE.EXE" Name="4DIAC-IDE.exe" Source="JenkinsCI\workspace\PC-manualPackage\Lee\MyApp\4DIAC-IDE.exe"&gt;
                              &lt;Shortcut Id="desktopShortcut" Directory="DesktopFolder" Name="MyApp" WorkingDirectory="INSTALLDIR" Advertise="yes" Icon="DesktopIcon.exe" IconIndex="0" /&gt;
                              &lt;Shortcut Id="ExeShortcut" Directory="ProgramMenuDir" Name="MyApp" Advertise="yes" Icon="StartMenuIcon.exe" IconIndex="0" /&gt;
                          &lt;/File&gt;
                      &lt;/Component&gt;
      ...
  
      &lt;/Directory&gt;
      &lt;Feature Id="DefaultFeature" Title="Main Feature" Level="1"&gt;
          &lt;ComponentRef Id="_.ECLIPSEPRODUCT" /&gt;
          &lt;ComponentRef Id="_4DIAC_IDE.EXE" /&gt;
          ...
      &lt;/Feature&gt;
      &lt;UI /&gt;
      &lt;UIRef Id="WixUI_Minimal" /&gt;
      &lt;Icon Id="DesktopIcon.exe" SourceFile="JenkinsCI\workspace\PC-manualPackage\Lee\MyApp\4DIAC-IDE.exe" /&gt;
      &lt;Icon Id="StartMenuIcon.exe" SourceFile="JenkinsCI\workspace\PC-manualPackage\Lee\MyApp\4DIAC-IDE.exe" /&gt;
  &lt;/Product&gt;
  &lt;/Wix&gt;
  </code></pre>
  
  <p>Note the Icon elements within Product, and the _4DIAC_IDE.EXE ComponentRef referring to the Id in the component for the application executable.</p>
  
  <p>Because heat generates the XML and applies the transform, there is no input XML to see. However running heat without applying the transform gives:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"&gt;
  &lt;Product Id="{097247DB-DD4A-4C8D-AF04-75A79143ABCD}" Language="1033" Manufacturer="PUT-COMPANY-NAME-HERE" Name="PUT-PRODUCT-NAME-HERE" UpgradeCode="{73482F22-9A23-4D02-8661-388599DC37A8}" Version="1.0.0.0"&gt;
      &lt;Package Compressed="yes" InstallerVersion="200" /&gt;
      &lt;Directory Id="TARGETDIR" Name="SourceDir"&gt;
          &lt;Directory Id="dirDE09E8843EFC6098356C132F8C772506" Name="Lee"&gt;
              &lt;Directory Id="dirBA2DB469295E757A153AE4E941866015" Name="MyApp"&gt;
                  &lt;Component Id="cmp6F02BEBF925E45E085A43C8E9129B40A" Guid="*"&gt;
                      &lt;File Id="fil5C63854A4E335C543D7ECE7BB88B2658" KeyPath="yes" Source="$(var.AppSource)\MyApp\.eclipseproduct" /&gt;
                  &lt;/Component&gt;
                  &lt;Component Id="cmpC186B297004F1D5F5F25B295B20B89A3" Guid="*"&gt;
                      &lt;File Id="filBE7304CBAC53C43B9DD86ED19DDD2E5E" KeyPath="yes" Source="$(var.AppSource)\MyApp\4DIAC-IDE.exe" /&gt;
                  &lt;/Component&gt;
  
                  ...
  
  
        &lt;/Directory&gt;
      &lt;Feature Id="ProductFeature" Level="1" Title="PUT-FEATURE-TITLE-HERE" /&gt;
      &lt;Media Id="1" Cabinet="product.cab" EmbedCab="yes" /&gt;
  &lt;/Product&gt;
  &lt;/Wix&gt;
  </code></pre>