Reputation: 1097
I have this WIX command that uses all invariant paths and it doesn't need a system environment (unlike this example http://weblogs.sqlteam.com/mladenp/archive/2010/02/23/WiX-3-Tutorial-Generating-filedirectory-fragments-with-Heat.exe.aspx):
"%wix%bin\heat.exe" dir "$(SolutionDir)Web\obj\$(Configuration)\Package"
-cg PACKAGEFILES -gg -g1 -sreg -srd -dr DEPLOYFOLDER
-var wix.PackageSource="$(SolutionDir)Web\obj\$(Configuration)\Package"
-out "$(SolutionDir)WebInstaller\PackageFragment.wxs"
It works great, except on our build server where the solution path has a space in it and this error is thrown:
heat.exe error HEAT5057: The switch '-var' does not allow the spaces from the value. Please remove the spaces in from the value: wix.PackageSource=C:\Build\Builds 1\26e27895ae75b7cb\CADPortal\src\trunk\Web\obj\Debug\Package
I can't change the path and it shouldn't be necessary anyway in my opinion.
My question is: How do I solve this? (I don't even get why WIX is making trouble over a quoted path/string var with a space)
Upvotes: 6
Views: 6097
Reputation: 1
I just ran into this issue and solved it by executing in the Solution Folder and using a relative path.
This works because I happen to be running heat within a PowerShell script that Jenkins is executing.
Based on the following assumptions:
The Question Asker's script might look like the following:
$SolutionDir = (get-item $PSScriptRoot).Parent.FullName
Set-Location $SolutionDir
& $env:WIX\bin\heat.exe" dir "$SolutionDir\Web\obj\$(Configuration)\Package"
-cg PACKAGEFILES -gg -g1 -sreg -srd -dr DEPLOYFOLDER
-var wix.PackageSource=".\Web\obj\$(Configuration)\Package"
-out "$SolutionDir\WebInstaller\PackageFragment.wxs"
Upvotes: 0
Reputation: 788
To include a variable and its definition using heat, use the following mechanism.
<?xml version="1.0" encoding="utf-8"?>
<Include>
<?define PackageSource="c:\somePath"?>
</Include>
<?include myinclude.wxi?>
to the wxs file:<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:wix="http://schemas.microsoft.com/wix/2006/wi">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="wix:Wix">
<xsl:copy>
<xsl:processing-instruction name="include">myInclude.wxi</xsl:processing-instruction>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<!-- Identity transform. -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Run heat and specify the -t parameter that points to the transform:
heat.exe dir "c:\somePath" -cg PACKAGEFILES -gg -g1 -sreg -srd -dr DEPLOYFOLDER -var PackageSource -t mytransform.xsl -out PackageFragment.wxs
This will create the PackageFragment.wxs file as intended, add the include statement using the xsl transform, and use the variable value from the wxi file when compiling the msi (using candle later on).
Upvotes: 8
Reputation: 1197
For this cases you can define a prepocessor variable in the Build section of the project properties, in your case PackageSource=Web\obj\$(Configuration)\Package
and reference in the heat call like
"%wix%bin\heat.exe" dir "$(SolutionDir)Web\obj\$(Configuration)\Package"
-cg PACKAGEFILES -gg -g1 -sreg -srd -dr DEPLOYFOLDER
-var var.PackageSource
-out "$(SolutionDir)WebInstaller\PackageFragment.wxs"
Upvotes: 5
Reputation: 1097
So I ended up coding some build event code that inserts the necessary definition into the Heat generated file at the top, but under the starting WIX tag. Personally I'm starting to question the power of WIX if you need to do this kind of shenanigans/hacks.
Anyway this is my full build event code for anyone that needs it. (It also finds an invariant path for MSBuild.exe and creates a web package.)
echo off
set THEME_REGKEY=HKLM\Software\Microsoft\MSBuild\4.0
set THEME_REGVAL=MSBuildOverrideTasksPath
REM Check for presence of key first.
reg query %THEME_REGKEY% /v %THEME_REGVAL% 2>nul || (echo No theme name present! & exit /b 1)
REM query the value. pipe it through findstr in order to find the matching line that has the value. only grab token 3 and the remainder of the line. %%b is what we are interested in here.
set THEME_NAME=
for /f "tokens=2,*" %%a in ('reg query %THEME_REGKEY% /v %THEME_REGVAL% ^| findstr %THEME_REGVAL%') do (
set THEME_NAME=%%b
)
REM Possibly no value set
if not defined THEME_NAME (echo No theme name present! & exit /b 1)
REM replace any spaces with +
set THEME_NAME=%THEME_NAME: =+%
if errorlevel 1 goto BuildEventFailed
%THEME_NAME%MSBuild "$(SolutionDir)Web\Web.csproj" /t:Build;Package /p:Configuration=$(Configuration)
if errorlevel 1 goto BuildEventFailed
"%wix%bin\heat.exe" dir "$(SolutionDir)Web\obj\$(Configuration)\Package" -cg PACKAGEFILES -gg -g1 -sreg -srd -dr DEPLOYFOLDER -var var.PackageSource -out "$(SolutionDir)WebInstaller\PackageFragment.wxs"
REM FUNC "HeatFix" - This inserts the var. definition in top of the heat generated fragment:
MOVE /Y "$(SolutionDir)WebInstaller\PackageFragment.wxs" temp.txt
(
FOR /F "tokens=*" %%A IN (temp.txt) DO (
ECHO %%A
IF "%%A" EQU "<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">" (
ECHO ^<^?define PackageSource^=^"$(SolutionDir)Web\obj\$(Configuration)\Package^"^?^>
)
)
) > "$(SolutionDir)WebInstaller\temp.txt"
move /Y "$(SolutionDir)WebInstaller\temp.txt" "$(SolutionDir)WebInstaller\PackageFragment.wxs"
REM END FUNC "HeatFix"
goto BuildEventOK
:BuildEventFailed
echo POSTBUILDSTEP for $(ProjectName) FAILED
exit 1
:BuildEventOK
echo POSTBUILDSTEP for $(ProjectName) COMPLETED OK
Upvotes: 2
Reputation: 35996
The -var
switch provides the name of a preprocessor variable. Something like var.Foo
. Preprocessor variable names cannot contain spaces in them. The value wix.PackageSource=Whatever SolutionDir Expands To\Web\obj\Whatever Configuration Expands To\Package
is not a valid name for a preprocessor variable because it has spaces in it. I expect the backslashes will be a problem as well.
Upvotes: 3