Msbuild exec task call msbuild

execmsbuildparameters

I need to call exec and build a wix setup project.

Currently I have the following in my 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)" />

I've tried to simply as much as possible so I don't get confused where the " are meant to be. When I run this the debug message (2nd last command) outputs

"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"

And I get the following error in the log

'"msbuild"' is not recognized as an
internal or external command,
operable program or batch file.
f:\builds\app\Installer
Build\BuildType\TFSBuild.proj(538,5):
error MSB3073: The command ""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""
exited with code 9009.

I'm not sure if this is being caused by not being able to call the msbuild command from the command line or a " issue. If it is because I can't call msbuild from the command line like this how would I go about referencing it, is there a property that points to it?

Best Answer

To start with, you don't need most of the quotes, especially if the paths you are using don't contain spaces, but I'd trim it down to this, allowing for spaces in the paths for $(WebRoot), $(DbRoot) and $(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)"
   />

However, you still won't be able to execute MSBuild with this, since the path to MSBuild isn't specified. It is typically found in the $(WINDIR)\Framework\Microsoft.Net\v4.0.30319 folder. There are a few ways to get this, either encode it directly, rely on an environment variable (that has to be set up somehow), use the predefined $(MSBuildBinPath), or extract it from the registry using the MSBuild registry syntax, which would look like this:

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

However, it isn't clear why you are running MSBuild using Exec rather than just using the MSBuild task. Change the line with Exec to this:

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

removing your declaration for <Configuration> and changing <DefineConstants> to this:

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