If you are using MSBuild 4.0 (i.e. Visual Studio 2010) then you can now use a new technique that I outline at MSBuild: Extending the solution build

Over the past few months I have noticed a need by many people to place some specific steps into the process that is used when MSBuild is invoked on solution files. When people research this topic they quickly discover that the Visual Studio Solution file is NOT in the MSBuild format. MSBuild is able to consume these files, but you are not able to actually extend the process used for the solution as a whole.
Recently there was an entry at the MSDN MSBuild Forum related to this issue. So I figured I'd put my two cents into the discussion as well.

For some background, when MSBuild needs to build a solution file, it is converted in memory to an MSBuild project file. If you have the envrionment variable msbuildemitsolution set to the value of 1. Then this file will be written out to a file. The file name will be SOLUTION_NAME.sln.proj.

Ok, previously there was another entry on the MSDN Forum about how to set an Envrionment variable using MSBuild. To let you know where I'm going with this, I'd like to have MSBuild be responsible for creating this file and for me to add steps before and after the building of my solution. The task to create the envrionment variable is shown below, this was written by Keith Hill and is at the previous link

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace Sedodream.MSBuild
{
    ///


    /// Taken from http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=73225&SiteID=1
    /// Written by Keith Hill
    ///

    public class SetEnvVar : Task
    {
        private string _variable;
        private string _value;
        [Required]
        public string Variable
        {
            get { return _variable; }
            set { _variable = value; }
        }
        [Required]
        public string Value
        {
            get { return _value; }
            set { _value = value; }
        }
        public override bool Execute()
        {
            Environment.SetEnvironmentVariable(_variable, _value);
            return true;
        }
    }
}

You can download this file at the bottom of this entry (SetEnvVar.cs).

So we need to take this file and create an assembly from it. Make sure to add Microsoft.Build.Framework and Microsoft.Build.Utilities to your project's references. Oh yeah you could skip this part of the process if you just make sure to set that envrionment variable, but that's no fun.

After you create this assembly place in a known location. I called this assembly Sedodream.MSBuild.dll and placed it in a folder named tasks one folder above the solution I was trying to build.

Now that we are done with that we need to create the msbuild file that will do the rest of the work for us.

The whole file is shown below and can be downloaded at the end of this blog (DreamCatcher_SlnBuild.proj)

<Project InitialTargets="SetMSBuildEmit"
   
DefaultTargets="BuildSolution"
   
xmlns=http://schemas.microsoft.com/developer/msbuild/2003>

<PropertyGroup>

<SharedTasksDir>..\tasks\SharedTasksDir>

<EnvAssemblyFilename>Sedodream.MSBuild.dllEnvAssemblyFilename>

<BuildSolutionDir>.\BuildSolutionDir>

PropertyGroup>

<ItemGroup>

<SlnFiles Include="$(BuildSolutionDir)*.sln"/>

ItemGroup>

<UsingTask AssemblyFile="$(SharedTasksDir)$(EnvAssemblyFilename)" TaskName="SetEnvVar"/>

<Target Name="SetMSBuildEmit">

<SetEnvVar Variable="msbuildemitsolution" Value="1"/>

Target>

<Target Name="BuildSolution" DependsOnTargets="SetMSBuildEmit">

<MSBuild Projects="@(SlnFiles)" Targets="Build"/>

<CreateItem Include="*.sln.proj">

<Output TaskParameter="Include" ItemName="SolutionMSBuildFiles"/>

CreateItem>

<MSBuild Projects="$(MSBuildProjectFile)"

Targets="DoBuildSolution"

Properties="@(SolutionMSBuildFiles->'theSolution=%(Filename)%(Extension)')"/>

Target>

<PropertyGroup>

<DoBuildSolutionDependsOn>

BeforeDoBuildSolution;

CoreBuildSolution;

AfterDoBuildSolution

DoBuildSolutionDependsOn>

PropertyGroup>

<Target Name="DoBuildSolution" DependsOnTargets="$(DoBuildSolutionDependsOn)" />

<Target Name="BeforeDoBuildSolution">

<Message Text="*****Before building your solution*****" Importance="high"/>

Target>

<Target Name="CoreBuildSolution">

<MSBuild Projects="$(theSolution)" Targets="Build"/>

Target>

<Target Name="AfterDoBuildSolution">

<Message Text="###After building your solution######" Importance="high"/>

Target>

Project>

 

Now all you need to do is to place this file into the folder that contains your solution and call msbuild on it with:
    >msbuild.exe DreamCatcher_SlnBuild.proj /t:BuildSolution
The DefaultTargets is set to BuildSolution so you can take that off actually.

The are many advantages to this solution like:
    1) You extend the solution build process in similar ways as extending the project build proces
    2) You can re-use any existing MSBuild tasks
    3) You can add more steps to the build process easily
    4) You can place this file into source control and all team members can use it.

If you need more info please let me know, I would explain further now but I'm not feeling very well currently.

 

Sayed Ibrahim Hashimi


SetEnvVar.cs(.9kb)

DreamCatcher_SlnBuild.proj(3.19kB)


Comment Section















Comments are closed.