Question

I'm trying to build an installer that includes a number of features and I'm using heat to harvest a directory of files for each feature.
My source directory structure looks something like this:

HarvestDir
          \FeatureA
                   \FeatureImpl.dll
                   \FeatureImpl2.dll
          \FeatureB
                   \FeatureImpl.dll
                   \FeatureImpl2.dll

So I execute heat.exe for each feature to create a fragment for each feature but I get basically identical fragments e.g.

[...] Source="SourceDir\FeatureImpl.dll"
[...] Source="SourceDir\FeatureImpl2.dll"

What I really want is something like this:

[...] Source="SourceDir\FeatureA\FeatureImpl.dll"
[...] Source="SourceDir\FeatureA\FeatureImpl2.dll"

and

[...] Source="SourceDir\FeatureB\FeatureImpl.dll"
[...] Source="SourceDir\FeatureB\FeatureImpl2.dll"

I could use -var to specify a separate variable to represent the source location for each feature, but then I'd have to pass values for these variables into the wixproj (and I'm going to have ~10 features).

So, is there any way I can include a relative path in my harvested fragment?

Was it helpful?

Solution 2

You can either assign your source paths in .wixproj in DefineConstants or you can assign them in a WIX include file but either way you will have to use "var" option to specify the variable being used for your sources.

If you want to use DefineConstant in wixproj then you will have to do something like

        <Target Name="BeforeBuild">
            <PropertyGroup>
              <DefineConstants>BINFOLDER=..\PATH\TO\SOURCE\$(Configuration)</DefineConstants>
            </PropertyGroup>    
            <HeatDirectory OutputFile="output.wxs" Directory="..\PATH\TO\SOURCE\$(Configuration)" DirectoryRefId="INSTALLFOLDER" ComponentGroupName="COMPONENTGROUPNAME" ToolPath="$(WixToolPath)" PreprocessorVariable="var.BINFOLDER" />    
        </Target>

In Heat task make sure you add any additional attributes that you might need. In case you have added a reference to your source project in the .wixproj then you may directly use the project reference variables in the "PreprocessorVariable" attribute. For example instead of var.BINFOLDER use var.MyProject.TargetDir.

If you want to use a WIX include file (.wxi) then declare your variables in an include file for example Variables.wxi:

        <?xml version="1.0" encoding="UTF-8"?>
        <Include>
          <?define PATH1="PATH\TO\SOURCE"?>
          <?define PATH2="$(var.PATH1)\$(Configuration)"?>
        </Include>

Now you will need to pass in PATH1 and PATH2 using the -var in the heat command line. Once you have your .wxs file you will then need to include the Variables.wxi file in that using

<?include Variables.wxi ?>

in your .wxs. The problem with this way is that you will have to either add this include directive manually each time you generate your WIX source files or you will have to inject it using XSL Transformation.

OTHER TIPS

Rather than using heat on each Feature* folder, you could just harvest the whole feature layout folder that you have created and have heat transform the results. I'm assuming that each subfolder is a feature. It's a simple matter of creating a ComponentGroup for each one that references all the components under it.

You'd then use the component groups like this:

    <Feature Id="FeatureA">
      <ComponentGroupRef Id="FeatureA"/>
    </Feature>
    <Feature Id="FeatureB">
      <ComponentGroupRef Id="FeatureB"/>
    </Feature>

Heat command (I actually use the HarvestDirectory target in WiX 3.7):

Heat.exe dir FeatureLayout -dr FeatureLayoutDir -srd -ag -sfrag -t FeatureLayout.xslt -out obj\Debug\__dir.wxs

FeatureLayout.xslt:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
    xmlns:wix="http://schemas.microsoft.com/wix/2006/wi"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    exclude-result-prefixes="wix"
    >

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="wix:Wix">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
      <xsl:for-each select="wix:Fragment/wix:DirectoryRef/wix:Directory">
        <wix:Fragment>
          <wix:ComponentGroup Id="{@Name}">
            <xsl:for-each select="descendant::wix:Component">
              <wix:ComponentRef Id="{@Id}"/>
            </xsl:for-each>
          </wix:ComponentGroup>
        </wix:Fragment>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

hit properties for the setup project, this is the command i'm using:

"%WIX%\bin\heat.exe" dir "$(SolutionDir)\Export\Release" -suid -dr bin -srd -cg ExportComponentGroup -var var.sourcePath -ag -sreg -out "$(SolutionDir)\SetupProject\AppExportDir.wxs"

the only thing else you need to define in the build tab is: check the check box for "define 'debug'preprocessor variable" and enter.

sourcePath=%SystemDrive%\App\Main\Export\Release\

this please make sure that you use the flags that you want like suid or -dr

for more information about the flags you have see here: http://wix.sourceforge.net/manual-wix3/heat.htm

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top