Thursday, July 26, 2007

Using our Task we built earlier

Using our Task we built in Automating your Team Builds with Team Foundation Server we are now going to configure it within the build project file. To start off we need to reference the compiled dll.

<UsingTask TaskName="Microsoft.Sdc.Tasks.File.Execute"
AssemblyFile="C:\TaskBuilds\Microsoft.Sdc.Tasks.dll" />

Lets say after the source is compiled you are now ready to execute an external application you wrote to configure an Web Site or something using the compiled output code you could do something like this:

<Target Name="AfterCompile">
<File.Execute TreatErrorsAsWarnings="true"
CommandLineArgs="-ws $(BinariesRoot)" />
Here the MSBUILD engine will call your File.Execute method
after it has finished compiling the solution.

Automating your builds in TFS

In development we consistently try to find ways to make our processes faster and more useful. As for deployment and test builds, Team Foundation Server has made it easy to automate your builds by use of Tasks performed within a build project. Developers can build classes implementing the Microsoft.Sdc.Tasks.TaskBase class (derived from Microsoft.Build.Utilities.Task) which has an overrided method named InternalExecute. As a short example to the powerful uses of this class I will demonstrate writing your own class that will handle executing an external application.

In this demonstration I will be using Micsoft.Sdc.Tasks source project to add my class.

First we need to create a class, I am doing so in the File folder as this pertains to files and System.IO. I will name this class Execute. Add the basic namespaces we will need:

using System;
using System.Xml;
using System.Globalization;
using System.IO;
using Microsoft.Build.Framework;
using System.Collections;
using System.Diagnostics;
public class Execute : TaskBase

We might want to add a property that allows us to
specify if an error occurs to treat it as a warning and move on.
/// <summary>
/// If TRUE any errors will be logged as warnings
/// </summary>
public bool TreatErrorsAsWarnings
get { return treatErrorsAsWarnings; }
set { treatErrorsAsWarnings = value; }
And of course we need Command Line Arguments:
private string _CommandLineArgs;
public string CommandLineArgs
return _CommandLineArgs;
_CommandLineArgs = value;
private ITaskItem file;

/// <summary>
/// The file to be Executed
/// </summary>
/// <value>An ITaskItem of file</value>
public ITaskItem File
get { return this.file; }
set { this.file = value; }

Now we need to override the Internal Execute method
so our code is called from the MSBUILD.
/// <summary>
/// Performs the action of this task.
/// </summary>
protected override void InternalExecute()
if (System.IO.File.Exists(File.ItemSpec))
// Display the File we are about to execute
base.Log.LogMessage("Executing File - " +
File.ItemSpec + "\rCommand Line Args - "+CommandLineArgs);
// Setup our startup information
ProcessStartInfo psi = new ProcessStartInfo();
string[] args = CommandLineArgs.Split(' ');

// Retrieve the arguments
if (args.Length > 0)
args[0] = "\"" + args[0] + "\"";
foreach (string str in args)
CommandLineArgs = str + " ";

CommandLineArgs = CommandLineArgs.TrimEnd(' ');
// Execute
psi.FileName = File.ItemSpec;
psi.Arguments = CommandLineArgs;
if (!TreatErrorsAsWarnings)
throw new
FileNotFoundException("File does not exists - " + File.ItemSpec);
base.Log.LogWarning("File does not exists - " +

catch (Exception ex)
if (TreatErrorsAsWarnings)

this.LogError(File, ex);

Now we have a class we can use to execute external files within
our team build. Notice the CommandLineArgs is expecting the
argument to be separated using the standard spacing (CHAR 32).
You can customize this to use commas or semicolons if you like.
Compile the Microsoft.Sdc.Tasks project and copy the dll to your team
server in the location you are keeping your automated build files.
To configure look out for Configuring your Customized Task in this blog.

Creative Commons License
Blogged Information and Code is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License.