Man I saw the topics list for the upcoming Roanoke Code Camp and man it looks good! Think I'll just have to mosey on down there and hang out with some .Net folks and my good ole friends Robin Edwards and Andy Leonard this coming weekend.
Roanoke Code Camp Registration.
And don't forget that the Richmond Code Camp is April 26th. I have a feeling that it will be be really good as well, so put it on you calender..
Look me up if you are going to be attending the Code Camp at Roanoke this weekeend. Se you there!
-Kevin
Check out the latest coding solutions with like-minded developers at MSDN Events. Witness the evolution of IIS and see why IIS7 is our most extensible, manageable and secure Web platform on record. You’ll learn how to extend application services – including membership, role management and navigation – from ASP.NET and how to consume them from a wide variety of clients. As a special bonus, we’re also tackling the biggest security risks and clueing you in to the top counter measures available for Websites and Web applications of all kinds. Don’t miss these free, live sessions that are really on your wavelength. Sign up today!
Richmond Area:
http://msevents.microsoft.com/cui/EventDetail.aspx?culture=en-US&EventID=1032359653
All others:
http://www.msdnevents.com/
Well along with making sure that I write the year as 2007 2008 correctly, the new year has brought forth many changes for me; some good, some great.
I am no longer working at CarMax (I do miss my many good friends there). I am working for the City of Richmond (VA) helping them implement Visual Studio Team System, helping them with ALM and CM, helping them move to a SOA, maybe some .Net Training with some standards and methodology thrown in.
I am no longer teaching at ECPI** but am going to be working for a company based out of NJ in a senior development role working with C# and SharePoint (gotta show some love for those telecommuting opportunities).
I bought a new Desktop and have switched everything over to Vista Business and am enjoying it very very much although I am definitely out of my comfort zone, let me tell you.
Finally purchased a new sever with Windows 2003 (yeah it can handle the upgrade to 2008, no problems there). Got it over the holidays, been working playing with WSS 3.0, SQL 2008 and TFS 2008 and Exchange 2007.
Installed Visual Studio 2008 Team System and I've got 2 words for ya...Wow and Wow.
Have joined INETA's technical team and will begin helping them complete development on thier new website.
Am contemplating setting up a Visual Studio Team System User Group here in the Richmond area (again Wow).
(My wife is reading this over my shoulder as I am typing this and is reminding me in a very nice irritated way that I left out the most important thing: I got a new gecko for Christmas, aptly named Reptar (Rugrats....heres lookin at you Andy
, and my kids who named him are 17 and 11!). Yes I ask for an Iguana, I get the Geico lizard hmm....Reptar is a leopard gecko, but I have yet to hear any accent!
I am looking forward to being more involved with the .Net community this year.
Last but not least, I am happy that my wife Sherri is staying home to spend more time with Hellion Hunter and Wild Child Nikki and me!
Happy New Year to everyone.
-Kevin
** Note - We will still be holding our .Net User Group meetings at ECPI Innsbrook along with our Code Camps....
Hello everyone! Man I am in love with this cooler weather. I've got a faculty conference coming up this week for ECPI so I wanted to get this last piece out there.
This is part 3 in a 3 part series and should give you a decent overview of customized builds through custom tasks using MSBuild with Visual Studio (2005 I hope) or using TeamBuild with Team Foundation Server and Visual Studio Team System.
In case you are just joining us I have included two links for your reference:
Now that we have covered how to add MSBuild to your VS IDE and how to create a custom build Task, the final destination on our path to a customized build process lays just in front of us.
The file that the build uses is a project file. Some of the characteristics of a project file are that its extension ends in .csproj or .vbproj (or simply .proj if using TeamBuild), that it contains metadata about a project and holds this metadata in an XML format and that it "communicates" with the build engine via a set of predefined "events" called targets and predefined instructions called tasks. Of course there are other cool things in the project file: Item Groups, Property Groups, Compile includes etc.
OK that's it...secrets out. Nothing magic. Predefined targets (sequential "events") in the project file that the build engine understands. We are done! Ok maybe not quite. Almost though.
Consider the following:
<Target Name="AfterBuild">
<Message Text="Executing AfterBuild target..." />
</Target>
The target name is "AfterBuild" and I bet you can't guess when it executes can you? If you said "Hey Kevin after the build completes!" then I would "Brilliant!". When watching your build progress output you will see a line of output that says "Executing AfterBuild target...". To recap, the target is "AfterBuild" and the task is "Message". Message is an "out of the box" task which has an attribute (property) called Text, which is set by an author when customizing the build.
Let's pretend that we need to implement our awesome BuildLogger Task which is part of our DemoCustomTasks project. We compile our project and create a folder called CustomTasks on our C drive (on the build machine). We stick the compiled DemoCustomTasks assembly in the CustomTasks folder.
Consider the following:
<UsingTask TaskName="DemoCustomTasks.BuildLogger" AssemblyFile="C:\CustomTasks\DemoCustomTasks.dll" />
<Target Name="BeforeBuild">
<Message Text="Executing BeforeBuild target..." />
<BuildLogger LogFileLocation="C:\test.txt" />
<Message Text="Completed BeforeBuild target..." />
</Target>
In the above code we use the UsingTask build node to identify 1) the namespace and type name of our custom Task and 2) the physical assembly that contains the custom Task. We place our custom Task within a Target, in this case "BeforeBuild". When BeforeBuild gets called by the build engine, the Tasks contained therein get called namely Message, BuildLogger and Message. Notice the correlation between:
<BuildLogger LogFileLocation="C:\test.txt" />
and
public class BuildLogger : Task
[RequiredAttribute]
public string LogFileLocation
Wow. It all seems to make sense somehow! Just a little more and we will finish this 3 part series. I want to show you a couple of additional things we can do in builds. The following example shows the use of a Property Group to create one or more reusable constants that can be referenced in the build.
<PropertyGroup>
<CustomTaskPath>C:\ CustomTasks </CustomTaskPath>
<LogFilePath>C:\ Build Log Files</LogFilePath>
</PropertyGroup>
<UsingTask TaskName="DemoCustomTasks.BuildLogger" AssemblyFile="$(CustomTaskPath)\ DemoCustomTasks.dll" />
<Target Name="BeforeBuild">
<BuildLogger LogFileLocation="$(LogFilePath)\buildlog.txt" />
</Target>
We can also create and call custom Targets that can then be called from pre-defined targets. This is done using the "DependsOnTargets" attribute of the pre-defined target.
<Target Name="BeforeBuild" DependsOnTargets="LogBuild" />
<UsingTask TaskName="DemoCustomTasks.BuildLogger" AssemblyFile="$(CustomTaskPath)\CustomTasks\DemoCustomTasks.dll" />
<Target Name="LogBuild">
<Message Text="Executing LogBuild target..." />
<BuildLogger LogFileLocation="$(LogFilePath)\buildlog.txt" />
<Message Text="Completed LogBuild target..." />
</Target>
It is my sincere hope that this has shed some light on how to customize your build process using either MSBuild or Team Build. In the future I will try to cover NAnt and CruiseControl.Net and some other topics like how to get information from the custom Task back to the build.
Take care! -Kevin
This is part 2 of a 3 part series aimed at understanding how to create and implement custom tasks using either MSBuild or TeamBuild. Click here for part 1. The overall presentation was given at the last Richmond .Net Code Camp.
In part 1 we covered how to add MSBuild to the Visual Studio IDE since the default build engine is not MSBuild. Team Build uses a simular build engine to MSBuild and the following code example will work in both. Now we move into creating custom tasks.
Custom tasks are created by utilizing Microsoft build assemblies. We reference those assemblies and then using those assemblies, (sorry couldn't help it
) we are able to develop our custom tasks by extending the Microsoft.Build.Utilities.Task class.
Start Visual Studio and select a C# project that is a class library. For this example we will call the project DemoCustomTasks. We will change the filename for our class to BuildLogger.cs and will also want to refactor the class name as needed. Set references to Microsoft.Build.Utilities and Microsoft.Build.Framework. Within the source code for my class I need to add 3 using statements:
using System.IO;
using Microsoft.Build.Utilities;
using Microsoft.Build.Framework;
So far my class essentially looks like this:
using System;
using System.IO;
using Microsoft.Build.Utilities;
using Microsoft.Build.Framework;
namespace DemoCustomTasks
{
public class BuildLogger
{
}
}
Since my class must inherit from Microsoft.Build.Utilities.Task, I make the following change...
using System;
using System.IO;
using Microsoft.Build.Utilities;
using Microsoft.Build.Framework;
namespace DemoCustomTasks
{
public class BuildLogger : Task
{
}
}
So far so good. Designing and coding our custom task is essentially the same as any other "normal" class with the exception that since we are inheriting from Microsoft.Build.Utilities.Task, we must conform to certain "inheritence rules" that we get from the base Task class.
The custom task "communicates" with the build via a publicly exposed method whose signature is public override bool Execute(). The Execute() method is derived from the base Task class and returns a boolean to the build, the build automatically uitlizes the Execute() method for the task, you don't directly call Execute() from the project file that contains build instructions, you only call the task. Logical implementation of the custom build functionality is obtained by creating one or more methods (access should be private) that get called within the implementation of Execute(). In our code example we have a LogBuild() method whose access is private and it gets called in Execute(). Consider:
public override bool Execute()
{
try
{
return LogBuild();
}
catch (Exception ex)
{
return false;
}
}
If the LogBuild() method fails then false gets returned to the build. If an exception is thrown then false gets returned to the build. Otherwise the result of LogBuild() is true.
In this example we are using a public property that the build will use to pass information to the task. We implement this property using standard class design.
private string _logFileLocation = String.Empty;
[RequiredAttribute]
public string LogFileLocation
{
get
{
return _logFileLocation;
}
set
{
_logFileLocation = value;
}
}
You will notice that we are decorating our property with the RequiredAttribute attribute (hee hee) that comes from Microsoft.Build.Framework. This forces the build author to set the property when executing the task.
The actual code for the LogBuild() method is not really that important, it is only there to demonstrate creating the custom task. It implements the logic for us to create a custom logging mechanism for our builds. (TFS logs everything about its builds, it may be useful to teams using a non-TFS version of VS??). Again, mainly for demo purposes.
private Boolean LogBuild()
{
bool hasLoggedBuild = false;
//would want to add logic to check for directory structure as well
if (!File.Exists(LogFileLocation))
{
File.CreateText(LogFileLocation);
}
FileStream fileStream = new FileStream(LogFileLocation,FileMode.Append, FileAccess.Write);
StreamWriter textWriter = new StreamWriter(fileStream);
try
{
textWriter.WriteLine("Build Completed @ " + DateTime.Now);
hasLoggedBuild = true;
}
catch (Exception ex)
{
textWriter.WriteLine("Logger Exception Message: " + ex.Message);
hasLoggedBuild = false;
}
finally
{
textWriter.Close();
textWriter.Dispose();
}
return hasLoggedBuild;
}
The full code for my task is below:
using System;
using System.IO;
using Microsoft.Build.Utilities;
using Microsoft.Build.Framework;
namespace DemoCustomTasks
{
public class BuildLogger : Task
{
private string _logFileLocation = String.Empty;
public override bool Execute()
{
try
{
return LogBuild();
}
catch (Exception ex)
{
return false;
}
}
[RequiredAttribute]
public string LogFileLocation
{
get
{
return _logFileLocation;
}
set
{
_logFileLocation = value;
}
}
private Boolean LogBuild()
{
bool hasLoggedBuild = false;
//would want to add logic to check for directory structure as well
if (!File.Exists(LogFileLocation))
{
File.CreateText(LogFileLocation);
}
FileStream fileStream = new FileStream(LogFileLocation, FileMode.Append, FileAccess.Write);
StreamWriter textWriter = new StreamWriter(fileStream);
try
{
textWriter.WriteLine("Build Completed @ " + DateTime.Now);
hasLoggedBuild = true;
}
catch (Exception ex)
{
textWriter.WriteLine("Logger Exception Message: " + ex.Message);
hasLoggedBuild = false;
}
finally
{
textWriter.Close();
textWriter.Dispose();
}
return hasLoggedBuild;
}
}
}
So the key points to remember when designing, creating and implementing custom tasks are:
-
Create a project that is a class library.
-
Reference the Microsoft.Build.Utilities and Microsoft.Build.Framework assemblies.
-
Use the referenced assemblies to implement a custom Task that inherits from Microsoft.Build.Utilities.Task.
-
Create a public method called Execute() that returns boolean to the build.
-
Call your implementation method from Execute();
-
Communicate from Build to Task and from Task to Build using Properties.
In the final part of this installment we will integrate our custom tasks into our project files to be used by MSBuild and Team Build (TFS). We will also look at CruiseControl.Net and NAnt. Talk to you then!
-Kevin
Last week I was out getting some R & R and took some time off blogging & technology in general (the only thing I used was my cell phone

). This week has been catch up

. I will have part 2 of Task Master ready soon!
To understand the build process, we must cover a few general points:
- The default Visual Studio build engine is not MSBuild. For the purposes of this blog, when writing custom tasks we employee either MSBuild or Team Build (build engine that Visual Studio Team Foundation Server uses).
- The build uses project files for build instructions (.csproj/.vbproj/.proj). The project file contains XML like build instructions which can be customized. MSBuild or Team Build "reads" the project file for those build instructions.
- The build file contains pre-defined targets to call tasks (both pre-defined and custom). You can roughly translate targets to build events. For example there is a BeforeBuild target as well as an AfterBuild target. Any guess as to when those targets "fire" during the build? Those pre-defined targets are known by MSBuild (or Team Build) as they are part of the Microsoft Build Framework. We can also create customized targets (covered later).
- We tie tasks to targets. A target can contain 1 or more tasks to execute when it is called. So you can also think of a target as a container for tasks. When BeforeBuild gets called, execute tasks x, y, and z.
With the preliminaries covered, will cover these items:
-
Part 1 - Adding MSBuild to your Visual Studio IDE....
-
Part 2 - Coding a custom task...
-
Part 3 - Adding the custom task to a build...
Additional material maybe available on http://kevinisrael.com
*******This blog will cover part 1. I will blog Part 2 and 3 in the next couple of days...*******
1) Adding MSBuild to your Visual Studio IDE

Click External Tools. From the next window click Add, then type MSBuild (or whatever..its just a name that makes sense right?). Much of this is setting up environment variables to use in the build...

For the Command, Select the browse button. Browse to the MSBuild.exe file. This is typically found in C:\Windows\Microsoft\Framework\version number\

After adding the Command, we need to add Arguments. Arguments consist of Project path \ FilePath and a switch...



At this point we add a switch /v:d (verbosity is detailed). We now add the initial directory.

Make sure that you have Use Output window selected.

Click Apply. Now when you want to launch MSBuild simply go to Tools and Click MSBuild...

Coming up on the next blog, Parts 2 and 3.
-
Part 2 - Coding a custom task..
-
Part 3 - Adding the custom task to a build...
Well all I can say is that I am a very lucky guy.
- Lucky to be passionate about technology.
- Lucky to be working in the wonderful storm that is .Net and the architecture that surrounds it.
- Lucky to be in technology at a time when it seems like, in someways, many of the rules we have lived by in past regarding software and systems are changing (for the better).
- Lucky to have friends like Andy Leonard who invite you to blog about your experiences on his super cool web site! Hopefully you will get some benefit to this blog in some way and if not, blame Andy for inviting me to blog here!

I will concentrate on these areas generally (although I reserve the right to expand on additional topics):
- Visual Studio Team System
- Team Foundation Server
- Design Patterns and Anti-Patterns
- Application Lifecyle Management
- Development Methodologies
- Code Optimization Techniques
- Enterprise Collaboration and Architecture
- Other
For my first blog, I would like to make sure everyone is aware of the Richmond Code Camp, this coming weekend. Please try to attend. There are going to be some cool topics being covered along with some great speakers. It is a wonderful event, I personally enjoy it although it ususally leaves me near comatose the next day. See you there! - Kevin