views:

544

answers:

2

Building a solution containing a web application project using MSBuild from powershell like this:

msbuild "/p:OutDir=$build_dir\" $solution_file

Works fine for me on 32-bit, but on a 64-bit machine I am running into this error:

error MSB4019: The imported project "C:\Program Files\MSBuild\Microsoft\VisualStudio\v9.0\WebApplications\Microsoft.WebApplication.targets" was not found. Confirm that the path in the declaration is correct, and that the file exists on disk.

I am using Visual Studio 2008 and powershell v2. The problem has already been documented here and here. Basically on 64-bit install of VS, the Microsoft.WebApplication.targets needed by MSBuild is in the Program Files(x86) dir, not the Program Files dir, but MSBuild doesn't recognise this and so looks in the wrong place.

The two solutions I have so far are not ideal:

  1. Manually copy the file on 64-bit from Program Files(x86) to Program Files. This is a poor solution - every dev will have to do this manually.
  2. Manually edit the csproj file so MSBuild looks in the right place. Again not ideal: I would rather not have to get everyone on 64bit to manually edit csproj files on every new project.

e.g.

<Import Project="$(MSBuildExtensionsPathx86)\$(WebAppTargetsSuffix)" Condition="Exists('$(MSBuildExtensionsPathx86)\$(WebAppTargetsSuffix)')" />

Ideally I want a way to tell MSBuild to import the target file form the right place from the command line but I can't work out how to do that. Any solutions?

A: 

This should work without any modifications on a 64 bit machine IF you run msbuild from a 32-bit prompt. Given this test file:

<Project 
   DefaultTargets="Test" 
   xmlns="http://schemas.microsoft.com/developer/msbuild/2003" 
   ToolsVersion="3.5">

  <Target Name="Test">
    <Message text="$(MSBuildExtensionsPath)"/>
  </Target>
</Project>

I get this result from a 32-bit PowerShell prompt on my x64 system:

PS> msbuild test.proj /nologo
Build started 3/26/2010 9:13:10 AM.
Project "C:\temp\test.proj" on node 0 (default targets).
  C:\Program Files (x86)\MSBuild
Done Building Project "C:\temp\test.proj" (default targets).

This also shouldn't be a problem if you run directly from VS because VS is a 32-bit app.

Keith Hill
Great workaround! You got me thinking, and calling the 32bit version of MSBuild which is in the C:\Windows\Microsoft.NET\Framework folder (the 64bit MSBuild is in the Framework64 folder) also works. Thanks!
James Allen
Yeah, I probably should have mentioned that I have 32-bit shell configured to use vcvarsall.bat (which by default use x86). My 64-bit shell passes in amd64 to that same batch file to configure my environment. Which BTW, wouldn't work except that I use a PSCX function called Invoke-BatchFile that makes the env variable changes made by vcvarsall.bat permanent to the shell.
Keith Hill
BTW, this is how I configure my different bitness shells: $vcargs = ?: {$Pscx:Is64BitProcess} {'amd64'} {'x86'}; $VS90VCVarsBatchFile = "${env:VS90COMNTOOLS}..\..\VC\vcvarsall.bat"; Invoke-BatchFile $VS90VCVarsBatchFile $vcargs. Invoke-BatchFile as I mentioned earlier is part of http://pscx.codeplex.com.
Keith Hill
+1  A: 

You have a couple of other alternatives:

Since MSBuild basically works off of environmental variables, you could always just change Program Files to be ProgramFiles (x86) before you start msbuild.

$env:ProgramFiles = ${env:ProgramFiles(x86)}

This should trick MSBuild into looking in the right place

The other approach I can think of is using Start-Job to run MSBuild from within the script. This is more of a general purpose workaround:

Start-Job {
   Import-Module YourProject
   Start-YourMsBuildProject
} -RunAs32

Hope this helps

Start-Automating
Or, run `C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\Tools\vsvars32.bat` which sets the environment variables.
Jim Schubert
Really good ideas, but I liked Keith's more so gave him the green tick. Would you have to set the env variable back again? I try not to go near them. Think your Start-Job idea is good, does it mean the 32bit version of msbuild is used?
James Allen