This blog has moved, permanently, to http://software.safish.com.

Wednesday, July 28, 2010

Running MSBuild using Powershell Script

I wanted to build a Visual Studio solution using MSBuild using a Powershell script. Surprisingly, I couldn't find a reference on the web that actually worked for me. I thought I'd post it here for future reference, as it applies to the execution of any executable from within Powershell. It was "Invoke-Expression" that I hadn't used before.
 
$baseDir = "C:\Test\"
$outputFolder = $baseDir + "Output"
$msbuild = "C:\Windows\Microsoft.NET\Framework64\v3.5\MSBuild.exe"
$options = "/noconsolelogger /p:Configuration=Release"
$releaseFolder = $baseDir + "MyProject\bin\Release"

# if the output folder exists, delete it
if ([System.IO.Directory]::Exists($outputFolder))
{
 [System.IO.Directory]::Delete($outputFolder, 1)
}

# make sure our working directory is correct
cd $baseDir

# create the build command and invoke it 
# note that if you want to debug, remove the "/noconsolelogger" 
# from the $options string
$clean = $msbuild + " ""MySolution.sln"" " + $options + " /t:Clean"
$build = $msbuild + " ""MySolution.sln"" " + $options + " /t:Build"
Invoke-Expression $clean
Invoke-Expression $build

# move all the files that were built to the output folder
[System.IO.Directory]::Move($releaseFolder, $outputFolder)

7 comments:

  1. Very useful post - helped me get up and running with this quickly.

    ReplyDelete
  2. Super helpful. Thank you for posting.

    ReplyDelete
  3. Hi, How would you add the /p:DefineConstants="FLAG1;FLAG2" option to the msbuild command u have mentioned above? When I used it like this:
    $flag1 = "MY_DEBUG_FLAG;MY_DEBUG2_FLAG"
    $mconsts = " /p:DefineConstants="
    $mmore = $mconsts + $flag1
    $build = $msbuild + " ""MySolution.sln"" " + $options + " " + $mmore + " /t:Build"
    power shell barfs saying: The term 'MY_DEBUG2_FLAG' is not recognized as the name of a cmdlet, function, script file, or operable program.

    Any help on this?

    ReplyDelete
  4. Looks a bit strange, because MSBuild itself looks much more suited for tasks like assigning paths, deleting dirs, creating dirs, calling MSBuild on solution, and then arranging the output items. Don't see any reason for pulling these tasks into PowerShell.

    ReplyDelete
    Replies
    1. Something has to kick of MSBuild in an automated deployment - it doesn't run itself!

      Delete
    2. Yep! But... Someone has to kick off PowerShell either :)

      We'd run an MSBuild script as an entry point for our continuous integration with literally no cmdline parameters, just MSBuild and the root build file Server.Proj which isn't the SLN file of course.

      This keeps all of the build process custom steps in the same media (i.e. MSBuild) instead of making it heterogeneous. There're tasks for which MSBuild isn't well-suited (e.g. loops), but it's been specifically crafted for what we see in the sample, like folder manipulation and spawning the SLN build process.

      It's possible to do this with PowerShell or bare CMD of course, but I think the more appropriate solution would be to throw in one more MSBuild file if we're anyway stuck with using it for build.


      PS I found this post while looking for some means for running MSBuild targets locally in a convenient manner from PowerShell (preferrably with target name completion :), but this one is more about just doing CMD batch style stuff with PowerShell. I'll keep on looking ;)

      Delete
  5. Hi find this post very useful! I want to kick off msbuild from powershell to get (using msbuild scripts ) some folders from vss recursively. This is becos I find it does the work much quicker and easier than when I use the vss commandline. I probably have not been able to get the syntax right from the commanline although I can get individual files ok. So rather than use ps to get the folders, I will use msbuild to get the folders and then use ps to perform the tasks I need.

    ReplyDelete

Note: Only a member of this blog may post a comment.