Click here to Skip to main content
Click here to Skip to main content
Go to top

Simple build script using Power Shell

, 13 Apr 2012
Rate this:
Please Sign up or sign in to vote.
Power shell build script for multiple projects and solutions using MSBuild, with an option to fix the build error during the build and continue, without restarting the complete build.

Introduction

The article is about writing a simple build script for multiple projects and solutions using Power Shell and MSBuild, with an option to fix the build error during the build and continue the build without having to restart the complete build.

Background

I had to put together a build script in a very short time, about an hour. I could write this power shell script for doing the build and it served my purpose well.

About the script

Overview of the build steps

The Image below outlines the build steps, that I have considered. As you can see its a vanilla flow. You may notice some of the build steps are missing from this diagram, some of them are omitted to keep this script as simple as possible. Some of these are:

  • Auto update source prior to build 
  • Controlling assembly version 
  • Auto-increment Version Number 
  • Build output path is not configurable. Will be taken from the project properties. 
  • Labelling source files. 

Extracting the latest source files

 

Step 1 : Close all DevEnv

Fix and continue feature expects the devevn process is not running, hence a request to close all the devenv is made in the beginning of the script. However this will not stop the script from running.

Step 2 : Initialize Build Configuration

Following are the build initialization and configuration used in the build.

  • Base directory for build
  • Handling dependency relationships (SolutionConfig.txt defines the order in which the solutions should be built)
  • Location of MSBuild.exe 
  • MS Build log configuration
  • Location of devenv
  • In case you are using any windows sdk tools in pre or post actions in the build, location of Windows SDK as part of the path.

Step 3: For every solution in the in the SolutionConfig.txt file do Build

  • Check if the file exists
  • The extension of the file is .sln. If you wish to include more files such as .csproj, vcxproj, etc you can do the necessary change in the script. This is to avoid errors in the SolutionConfig.txt file.

Step 4: MSBuild

MSBuild is a platform for building applications. Using MSBuild we can build projects on systems where visual studio is not installed. To read more about MSBuild visit MSDN MSBuild.

Step 5: Resolving a broken build

To be able to resolve a broken build, you need to run this script on a machine that has Visual Studio installed. The script will launch Visual studio and open the solution that was failed. Once resolving all the errors, close visual studio to continue building next solution in the order.

Step 6: Complete build

Build will successfully complete if all the projects compile without errors. In case you choose not to fix the error, the build will terminate in an error.

Putting it all together

Clear-Host

Write-Host "Please make sure you do not have any instances of Visual studio running before running the script..." -ForegroundColor Red -BackgroundColor White
Write-Host "You have 10 seconds" -ForegroundColor Red -BackgroundColor White

Start-Sleep -s 10

$baseDirectory = "D:\Project1\Source"
$solutionFilesPath = "$baseDirectory\SolutionConfig.txt"
$projectFiles = Get-Content $solutionFilesPath 

$msbuild = "C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe"
$MSBuildLogger="/flp1:Append;LogFile=Build.log;Verbosity=Normal; /flp2:LogFile=BuildErrors.log;Verbosity=Normal;errorsonly"

$devenv = "C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe"

$action = "Y"

# $env:Path = $env:Path + ";C:\Program Files\Microsoft SDKs\Windows\v7.0A"

foreach($projectFile in $projectFiles)
{
    if ($projectFile.EndsWith(".sln")) 
    {
        $projectFileAbsPath = "$baseDirectory\$projectFile"
        
        $filename = [System.IO.Path]::GetFileName($projectFile); 
        $action = "Y"  
        while($action -eq "Y") 
        {
            if(Test-Path $projectFileAbsPath) 
            {
                Write-Host "Building $projectFileAbsPath"
                & $msbuild $projectFileAbsPath /t:rebuild /p:PlatformTarget=x86 /fl "/flp1:logfile=$baseDirectory\msbuild.log;Verbosity=Normal;Append;" "/flp2:logfile=$baseDirectory\errors.txt;errorsonly;Append;"
                #& $devenv $projectFileAbsPath /Rebuild
                
                if($LASTEXITCODE -eq 0)
                {
                    Write-Host "Build SUCCESS" -ForegroundColor Green
                    Clear-Host
                    break
                }
                else
                {
                    Write-Host "Build FAILED" -ForegroundColor Red
                    
                    $action = Read-Host "Enter Y to Fix then continue, N to Terminate, I to Ignore and continue the build"
                    
                    if($action -eq "Y")
                    {
                        & $devenv $projectFileAbsPath
                        wait-process -name devenv    
                    }
                    else 
                    {
                        if($action -eq "I")
                        {
                            Write-Host "Ignoring build failure..."
                            break
                        }
                        else
                        {
                            Write-Host "Terminating Build... Please restart the build once the issue is fixed." -ForegroundColor Red
                            break
                        }
                    }
                }
            }
            else
            {
                Write-Host "File does not exist : $projectFileAbsPath"
                Start-Sleep -s 5
                break
            }
        }
        
        if($action -eq "N")
        {
            break;
        }
        
    }
}
 

Remember to set the Language of your code snippet using the Language dropdown.

Use the "var" button to to wrap Variable or class names in <code> tags like this.

Points of Interest

Logging MS Build out put to file

MSBuild provides pretty extensive mechanism for logging the build output and error. Following script creates 2 log files one for successful build and the other for error.

$msbuild = "C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" 

$MSBuildLogger="/flp1:Append;LogFile=Build.log;Verbosity=Normal; /flp2:LogFile=BuildErrors.log;

& $msbuild $projectFileAbsPath /t:rebuild /p:PlatformTarget=x86 /fl "/flp1:logfile=$baseDirectory\msbuild.log;Verbosity=Normal;Append;" "/flp2:logfile=$baseDirectory\errors.txt;errorsonly;Append;" 

Waiting for the process to exit

To wait for the process to exit in power shell I am waiting by the name of the process, this can be done with respect to a process id as well.

Wait-Process -name devenv

Alternatively, following command can be used to start a process and wait for its completion.

Start-Process $devenv -NoNewWindow -Wait

Or

$proc = Start-Process <path to exe> -NoWindow
$proc.WaitForExit()

Validate if path exists 

To check if a directory or a file exis we can use Test-Path command let.Test-Path can also be used to verify if a registry entry exist when used with Windows PowerShell registry provider. 

SVN Update and Labelling Source 

If you are using SVN as your source control you can include the following command to update your source before performing any of the steps as per the flow chart above. Its required to add the path of svn to the $env.Path. If you need to checkout more than one folder, you can specify the url of multiple folders in a single command separated by a spaces. 

& svn co $repositoryUrl1 $repositoryUrl2 $destinationDir   

To label source files in SVN after successful builds, you can create tags. This is usually associated with a successful build, successfully generating a incremental version number for the assemblies being build. 

Win SDK Tools 

When Projects build using .Net 4.0 as target framework Windows Sdk was not working with the default win sdk folder that is referenced by Visual stuido 2010. The additional path that needs to be referenced for .Net 4.0 dlls is:

C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\NETFX 4.0 Tools

By default the path referenced by visual studio 2010 is:

C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin

References

MSBuild Reference

Windows PowerShell Reference 

Handling Dependency Relationships 

The Build Process  

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Vivek Krishnamurthy
Architect
India India
No Biography provided

Comments and Discussions

 
QuestionMy Vote of 5 PinmemberThomas Maierhofer (Tom)4-Sep-14 10:36 
GeneralMy vote of 5 PinmemberThomas Maierhofer (Tom)4-Sep-14 10:32 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140916.1 | Last Updated 13 Apr 2012
Article Copyright 2012 by Vivek Krishnamurthy
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid