6

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)

4

5 回答 5

8

要使用热量包含变量及其定义,请使用以下机制。

  1. 创建一个包含 (myinclude.wxi) 文件,在其中定义变量及其值:
<?xml version="1.0" encoding="utf-8"?>
<Include> 
  <?define PackageSource="c:\somePath"?>
</Include>
  1. 创建一个 xsl 文件 (mytransform.xsl) 以将其添加<?include myinclude.wxi?>到 wxs 文件中:
<?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>
  1. 运行 heat 并指定指向变换的 -t 参数:

    heat.exe dir "c:\somePath" -cg PACKAGEFILES -gg -g1 -sreg -srd -dr DEPLOYFOLDER -var PackageSource -t mytransform.xsl -out PackageFragment.wxs

这将按预期创建 PackageFragment.wxs 文件,使用 xsl 转换添加包含语句,并在编译 msi 时使用 wxi 文件中的变量值(稍后使用蜡烛)。

于 2015-04-28T21:17:52.053 回答
5

对于这种情况,您可以在项目属性的 Build 部分中定义一个前处理变量,在您的情况下PackageSource=Web\obj\$(Configuration)\Package

并在热呼叫中参考,例如

"%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"
于 2014-03-24T13:06:21.840 回答
3

-var开关提供预处理器变量的名称。类似的东西var.Foo。预处理器变量名称中不能包含空格。该值wix.PackageSource=Whatever SolutionDir Expands To\Web\obj\Whatever Configuration Expands To\Package不是预处理器变量的有效名称,因为其中包含空格。我预计反斜杠也会成为问题。

于 2013-05-28T15:26:30.210 回答
2

所以我最终编写了一些构建事件代码,将必要的定义插入到顶部的 Heat 生成文件中,但在起始 WIX 标记下。如果你需要做这种恶作剧/黑客,我个人开始质疑 WIX 的力量。

无论如何,这是我为任何需要它的人提供的完整构建事件代码。(它还为 MSBuild.exe 找到一个不变的路径并创建一个 Web 包。)

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
于 2013-05-31T09:25:58.577 回答
0

我刚刚遇到这个问题并通过在解决方案文件夹中执行并使用相对路径来解决它。

这是因为我碰巧在 Jenkins 正在执行的 PowerShell 脚本中运行热。

基于以下假设:

  • 使用您的构建方法执行 PowerShell 脚本是合乎情理的
  • PowerShell 脚本位于解决方案目录的文件夹中

提问者的脚本可能如下所示:

$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"
于 2021-08-05T17:47:59.923 回答