使用MSBuild exec任务调用MSBuild

3

我需要调用exec并构建一个wix安装包项目。

目前在我的TFSbuild.proj文件中有以下内容:

 <PropertyGroup>
      <WebRoot>$(DropLocation)\Latest\x86\Release\_PublishedWebsites\Web</WebRoot> 
      <DBRoot>$(DropLocation)\Latest\x86\Release\Database</DBRoot> 
    </PropertyGroup>

 <PropertyGroup>
      <Msbuildexe>&quot;msbuild&quot;</Msbuildexe>
      <Configuration>&quot;/p:Configuration:&quot;Release&quot;&quot;</Configuration>
      <DefineConstants>&quot; /p:DefineConstants:&quot;WebRoot=$(WebRoot);DBRoot=$(DBRoot)&quot;&quot;</DefineConstants>
      <WixSolution>&quot;$(MSBuildProjectDirectory)\Setup\Setup.sln&quot;</WixSolution>
    </PropertyGroup>

    <Message Text="Bulding setup solution" />
    <Message Text="$(Msbuildexe) $(Configuration) $(DefineConstants) $(WixSolution)" />
    <Exec Command="$(Msbuildexe) $(Configuration) $(DefineConstants) $(WixSolution)" />

我尽可能地简化了这个命令,以免混淆引号的位置。当我运行它时,调试消息(倒数第二个命令)输出:
"msbuild" "/p:Configuration:"Release"" "/p:DefineConstants:"WebRoot=\server\drops\app\Installer Build\Latest\x86\Release_PublishedWebsites\Web;DBRoot=\server\drops\app\Installer Build\Latest\x86\Release\Database"" "f:\builds\app\Installer Build\BuildType\Setup\Setup.sln"
然后我在日志中得到以下错误:
'"msbuild"' 不是内部或外部命令,可执行的程序或批处理文件。 f:\builds\app\Installer Build\BuildType\TFSBuild.proj(538,5): error MSB3073: 命令 ""msbuild" "/p:Configuration:"Release"" "/p:DefineConstants:"WebRoot=\server\drops\app\Installer Build\Latest\x86\Release_PublishedWebsites\Web;DBRoot=\server\drops\app\Installer Build\Latest\x86\Release\Database"" "f:\builds\app\Installer Build\BuildType\Setup\Setup.sln"" 已退出,代码为 9009。
我不确定是否由于无法从命令行调用 msbuild 命令还是引号问题导致的。如果是因为我无法像这样从命令行调用 msbuild,那么我该如何引用它?是否有一个指向它的属性?

我可能会漏掉一些东西,但是为什么你需要执行 Exec MSBuild 而不是只添加一个 MSBuild 任务 - Filburt
2个回答

1
首先,您不需要大部分引号,特别是如果您使用的路径不包含空格,但我会将其缩减到以下内容,以允许$(WebRoot)、$(DbRoot)和$(MSBuildProjectDirectory)中的路径包含空格:
<PropertyGroup>
   <WebRoot>$(DropLocation)\Latest\x86\Release\_PublishedWebsites\Web</WebRoot>
   <DBRoot>$(DropLocation)\Latest\x86\Release\Database</DBRoot>
</PropertyGroup>
<PropertyGroup>
   <MsbuildExe>{still-needs-a-path-to}\msbuild</MsbuildExe>
   <Configuration>/p:Configuration:Release</Configuration>
   <DefineConstants>/p:DefineConstants:&quot;WebRoot=$(WebRoot);DBRoot=$(DBRoot)&quot;</DefineConstants>
   <WixSolution>&quot;$(MSBuildProjectDirectory)\Setup\Setup.sln&quot;</WixSolution>
</PropertyGroup>
<Message
   Text="Bulding setup solution"
   />
<Message
   Text="$(MsbuildExe) $(Configuration) $(DefineConstants) $(WixSolution)"
   />
<Exec
   Command="$(MsbuildExe) $(Configuration) $(DefineConstants) $(WixSolution)"
   />

然而,即使如此,您仍无法使用此执行MSBuild,因为未指定MSBuild的路径。通常可以在$(WINDIR)\Framework\Microsoft.Net\v4.0.30319文件夹中找到它。有几种方法可以获得它,直接编码、依赖于环境变量(必须以某种方式设置),使用预定义的$(MSBuildBinPath),或者使用MSBuild注册表语法从注册表中提取它,其语法如下:

$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\4.0\MSBuildToolsPath)

然而,目前不清楚您为什么要使用Exec来运行MSBuild,而不是直接使用MSBuild任务。请将Exec的那一行改为以下内容:

<MSBuild
   Project="$(WixSolution)"
   Properties="$(DefineConstants)"
   />

移除你的 <Configuration> 声明并将 <DefineConstants> 更改为以下内容:

   <DefineConstants>Configuration=$(Configuration);WebRoot=$(WebRoot);DBRoot=$(DBRoot)</DefineConstants>

定义常量是一个属性列表,我需要覆盖它本身,但似乎msbuild任务无法处理这个问题...请参见https://dev59.com/OnRB5IYBdhLWcg3wz6QJ。感谢您的答案! - Daniel Powell
我不认为我可以使用那里提出的解决方法,因为我们正在使用TFS 2008,我认为它使用的是MSBuild 3.5?即使我在exec任务中调用4.0 msbuild,执行它的msbuild也应该是3.5吧?虽然我可能错了! - Daniel Powell
如果您正在使用3.5,则路径将是v3.5而不是v4.0.30319,注册表路径将有3.5而不是4.0,但除此之外,它的工作方式相同。MSBuild可以处理覆盖组成DefineConstants的单个属性或整个值,只需使用类似于Condition =“'$(DefineConstants)' ==''”这样的条件,如果属性已经具有值,则重新声明将被跳过。 - Brian Kretzler
哦,是的,忘记添加$(MSBuildBinPath)了,这是一个带有路径的保留属性,我已经将其添加到上面了。 - Brian Kretzler

0

针对我的评论,我建议您尝试使用MSBuild任务而不是Exec

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="BuildWiXSolution">
    <!-- Include the custom build targets installed with WiX -->
    <Import Project="$(MSBuildExtensionsPath)\Wix\Wix.targets"/>

    <PropertyGroup>
        <WebRoot>$(DropLocation)\Latest\x86\Release\_PublishedWebsites\Web</WebRoot> 
        <DBRoot>$(DropLocation)\Latest\x86\Release\Database</DBRoot> 
    </PropertyGroup>

    <ItemGroup>
        <WiXSolution Include="$(MSBuildProjectDirectory)\Setup\Setup.sln">
            <Properties>Configuration=Release</Properties>
            <AdditionalProperties>WebRoot=$(WebRoot);DBRoot=$(DBRoot)</AdditionalProperties>
        </WiXSolution>
    </ItemGroup>

    <Target Name="BuildWiXSolution">
        <MSBuild Projects="@(WiXSolution)" />
    </Target>  
</Project>

它允许您将配置属性和附加属性与您的Wix解决方案一起保存。


我认为附加属性不起作用,因为DefineConstants实际上是一个具有其中定义的属性列表的属性。 - Daniel Powell
@Daniel,像您的代码示例那样将DefineConstants封装起来应该是可行的——我只是为了易读性而将其缩短了。 - Filburt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接