January 31, 2011 7:33 PM | Comments [13] | by Ed Blankenship
By default, when you are setting up a new build definition in TFS 2010 that uses multiple Visual Studio solutions and projects, you end up with a drop folder with all of the compiled assemblies dropped in the root. One notable exception to this is for web application projects where you will end up with a subfolder underneath the _PublishedWebsites folder for each of the web application projects. You may not want everything to be in the root and instead want it organized. There were several methods for how to do this using TFS 2005 or TFS 2008 but let me show you a way to do it for a TFS 2010 Build.
Open up your build process template file and go to your “Arguments” tab (available in the lower-left hand corner of the workflow designer) to add a new workflow parameter. My suggestion would be to use a new Boolean argument named “CustomizableOutputDirectory” as shown below.
Next, open up the Process Parameter Metadata Editor by clicking on the editor button for the Metadata workflow argument that is already defined. Next, give your new process parameter some extra information so that someone editing the build definition will understand what this parameter is for. You’ll notice that I’m also putting this parameter in the Advanced category since I don’t really need to create another category for only one new parameter. Feel free to create a new grouping if you have more custom parameters in your build process template.
Once you finish these steps and check-in the file to version control, you’ll see your new parameter in the build definition editor as shown below.
The next step is to add in the appropriate functionality for the customizable output directory. What we will end up doing is adding an alternate path for when MSBuild is called to compile the Visual Studio solution or project each time. I want to leave the default functionality though if the process parameter we created above is set to False. So, the first step is to find the default functionality for compilation. You can find it by navigating deep into the workflow and finding the “Compile the Project” sequence activity that contains the MSBuild activity that is used for compilation. You can find it by navigating through these activities:
The next step I would take is to drag and drop a new If activity and place the existing MSBuild activity in the Else container. This allows for the default functionality to still continue if the value of the custom process parameter is False. Set the Condition parameter for the If activity to the name of the custom process parameter that was defined earlier as shown below.
You will notice in the MSBuild activity that exists for default functionality, the CommandLineArguments workflow activity argument is set to the following.
String.Format("/p:SkipInvalidConfigurations=true {0}", MSBuildArguments)
To implement our custom output directory functionality, we are essentially going to modify this one activity parameter to pass in a new value. This will be the new expression that we will use for the MSBuild activity parameter:
String.Format("/p:SkipInvalidConfigurations=true;TeamBuildOutDir=""{0}"" {1}", outputDirectory, MSBuildArguments)
The easiest way to do this would be to copy the existing MSBuild activity and paste it in the Then container for our If activity. You can then set the CommandLineArguments parameter for the copied activity to the new value that defines the new MSBuild parameter.
Extra Credit Aside: Anyone know why we used outputDirectory instead of BinariesDirectory?
Once you have done all of the steps, you’ll notice that it didn’t actually change anything . For each of the Visual Studio projects that you want to use the new functionality, you will need to “opt-in” by editing the .csproj or .vbproj Visual Studio project files and adding the new MSBuild property group shown below.
<!-- Customizable Output Directory Opt-In for TFS Build (non-web application projects) --><PropertyGroup Condition="$(TeamBuildOutDir) != '' "> <OutputPath>$(TeamBuildOutDir)\$(SolutionName)\$(MSBuildProjectName)</OutputPath></PropertyGroup>
The change does break the _PublishedWebsites functionality for any web application projects though and you will need to use a different opt-in below for every web application project that is included in the build.
<!-- Customizable Output Directory Opt-In for TFS Build (web application projects) --><PropertyGroup Condition="$(TeamBuildOutDir) != '' "> <OutDir>$(TeamBuildOutDir)</OutDir></PropertyGroup>
There you go… Check those project file changes into version control and you can now queue a new build and the outputs for each of the projects that are opting-in to this new functionality are created in subfolders in the drop folder. It was also still continue to put web application projects into the _PublishedWebsites folders.
Ed Blankenship
Where/how do you define the 'outputDirectory' argument that is passed into the MSBuild arguments? Is it a new argument that I create and add to the template?
Remember Me
a@href@title, b, blockquote@cite, em, i, strike, strong, sub, sup, u