Saturday, January 4, 2014

TFS API: Get Project Collection Team Members

I have been working extensively with TFS (Team Foundation Service) API, and enjoying the miscellaneous challenges therein. One such challenge was to display a list of valid team members to assign work items to. And following the TFS online experience, the Assign To field must display all the user oat the collection level.

I saw a couple of approaches using the IGroupSecurityService interface that is a part of the Microsoft.TeamFoundation.Server but it has been marked as obsolete and instead a hint is provided to use the better alternative which is IIdentityManagementService. So here is a simple code snippet on how to get a list of team members ordered alphabetically.

Please note that the collection variable is simply an instance of  the team project collection class

new TfsTeamProjectCollection(collectionUrl, credentials)

Also note that when developing using the TFS API, you will need the following assemblies and namespaces referenced:
using Microsoft.TeamFoundation;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;

among others..

Here is the snippet::


Friday, October 5, 2012

A little recognition goes a long way

Blogging is an ambivalent activity. It is simultaneously the source of both gratifying sense of achievement, and at the same time, the source of the dreadful to-do chore that looms undone on your ever growing to-do list. It's an ugly sensation, being weighed down by your own device.. those evil to-do's.

But this post is not about that. It is more related to, or more precisely, due to one of those rare moments of recognition, that come unsolicited and utterly unexpected. That simple act of being recognized or thanked for your humble work and contribution to the infinitude of collective consciousness and knowledge base of the human civilization.

In this context, my humble work is an article I wrote for CodeProject almost 4 years ago, about implementing a custom Provider using the Workflow Foundation, which at the time was still fresh out of the oven of the Microsoft kitchen. It seems that it still serves some use after all:



So stay motivated and always B#!

Tuesday, August 23, 2011

But Scully…

Ok I could not help this one. I personally rank this Mulder-ian plead as one of top 5 most bizarre and fascinating TV quotes of all time.

Season six, episode seven (Terms of Endearment)

“(on the phone): Scully, this is a classic case of demonic foetal harvesting. – what they called in the middle ages: atum nocutrnem…”

Those pesky demon foetal harvester are the worst!

Beware of the dark lords of the underworld!

Saturday, August 20, 2011

Balsamiq… The art of software

Despite the infinite plethora of software and productivity and tools that have been around for years, most hailed by their users, many condemned for being utterly useless.

Every once in a while I stumble upon a gem, a singular piece of software or productivity tool that compels me with teary eyes to exclaim with sheer joy and awe (ok the tears part is an exaggeration).

The ability of providing quick intuitive diagrams and mock ups in software development is of paramount importance and using generic graphic software like photoshop is an overkill.

Enter Balsamiq… an amazing tool for impressive mock up design. It allows me to produce almost effortlessly intuitive diagrams such as this architectural diagram I was tasked with producing.

Balsamiq_mockup_sample

I love the artistic style of the graphics and font sets. In short this is a darn cool piece of software. If only more such beautiful tools exist.

Enjoy!

Thursday, August 18, 2011

The X-Files… The Third Marathon, I still want to believe

Where did this come from? From the #-ness of programming languages to the X – Files. An interesting tangent, being the only topic that compelled me to pollute my blog with non programming posts.

Yes, it is my third marathon watching the entire 9 seasons since the show’s finale almost a decade ago now. This is a no trivial undertaking and surely not for the faint of heart. In this day and age of instant gratification and extreme reductionism that plagues the media – yes, I am fed up with the over simplification of all that is television these days, it is difficult to appreciate verbose dialogues and absurd intellectual jousts such as the ones that Scully and Mulder exchanged throughout the series. For me, they are pure joy and a twisted thrill. But I digress..

I decided here to share some of the memorable puns/quotes/aphorisms that I immensely enjoyed.

This one comes from season 8, episode 10 (Salvage). Mulder has been abducted as a cliff hanger from the previous season. And awaiting his Christ-like resurrection, a great actor (Robert Patrick, as agent DOGGETT) takes his place as a leading man. What an excellent choice. Many of us grew up revering him as T – 1000 from Terminator II. The very reference to which (i.e. his role as the liquid metal menace from the future) is very clear in this piece of dialogue:

“(to Scully on the phone): What are you saying? Ray Pearce has become some kind of metal man? Because that only happens in the movies, Agent Scully”

I just loved the series with all the idiosyncrasies and the Orwellian overtones that flavoured every single Mulder-ian retort!

The truth is out there.

Sunday, August 7, 2011

Custom Assembly Versioning with VS 2010 and MSBUILD

There is a plethora of resources that deal with auto incrementing build numbers and a wealth of plugins and other gizmos that manage assembly versioning. So why yet another article. The truth is that none of those option solved my problem. I needed something simple, easy to maintain and most importantly flexible with a local .NET flavour. So naturally I had to write my own humble solution.

One of the daunting tasks we often face when deploying assemblies, is managing assembly and product versions. In any “decent” .NET solution, there is a need to auto-increment the version with every successful build. For example, incrementing the duild part of the assembly version in this default scheme

Major.Minor.Build.Revision

Sometime, versioning requirements are more elaborate and demanding, we might want to append the build date as well as incrementing the build number, the version scheme might look like

Major.Minor.Build.DDMMYYYY

For that purpose I prefer using the AssemblyFileVersion instead of the AssemblyVersion. The former has an open format and can accommodate virtually any data, whereas the later, AssmeblyVersion is intended for use by the .NET framework and enforces a strict numbering scheme that yields compiler errors if infracted.

[assembly: AssemblyVersion("4.0.*")] //Strict Format, for framework use
[assembly: AssemblyFileVersion("4.0.20.110708")] //Flexible Format more suitable for product versions

This post describes how to leverage MSBUILD to automate this process and include it in the continuous integration pipeline.

Tips for managing multiple assembly.cs files

In a solution with multiple projects and corresponding multiple assembly.cs files where AssemblyVersion and AssemblyFileVersion are kept, it is better to have one such file shared amongst all assemblies. To achieve this, we use a very useful visual studio feature which is Adding Existing Items as Links

Add as Link in VS2010

We use this technique to create one shared assembly info file to be shared amongst all the projects in the solution. This shared file will contain the AssemblyVersion and AssemblyFileVersion assembly attributes are well as any solution wide values, whereas the individual project level assembly.cs will contain project specific information such as:

using System.Reflection;
using System.Runtime.InteropServices;

[assembly: AssemblyTitle("POC.AssemblyVersioning.Common")]
[assembly: AssemblyCulture("")]

[assembly: Guid("bdf2e8b4-41aa-4569-b093-987439090dea")]

And here is how the solution structure will look like with implementing this scheme.. all for the sole purpose of facilitating modifying assembly version automatically.

solution view

And now to the more interesting part

Building custom MSBUILD tasks

The reason why I prefer to use custom tasks in build automation as opposed to other scripting solution, is the glaring fact that Build Tasks are plain C# classes, where you can use the goodies that the .NET framework offers. To create a Build Tasks all you have to do is:

  • Add references to the required .NET assemblies

references

  • Create a class that extends Microsoft.Build.Utilities.Task
  1. public class MyTask : Task
  2. {
  3.     // The only behaviour that need be overridden
  4.     public override bool Execute()
  5.     {
  6.         throw new NotImplementedException();
  7.     }
  8. }

<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="4.0" DefaultTargets="AutoIncrement" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <UsingTask AssemblyFile="POC.AssemblyVersioning.BuildTask.dll" TaskName="BuildIncrementTask" />
  <Target Name="AutoIncrement">
    <BuildIncrementTask />
  </Target>
</Project>

And to simply invoke this task from a command line, we use this familiar syntax, assuming that the msbuild file was saved as sample.proj

msbuild sample.proj /t:AutoIncrement

Putting it all together!

After having acquainted ourselves with MSBUILD tasks and thought about having one shared assembly file info that hosts the AssemblyVersion and AssemblyFileVersion attributes, I introduce here a simple way to go about updating those attributes through this simple custom task. The task is based on file I/O where the contents of the shared assembly info will be parsed, the attributes update and incremented (or transformed to the desired format) and the content re-written back to the file. Here is the source code for the simple build tasks that will perform the file manipulation. This is for illustration purposes and intended only as a guide to creating your own build task. I encourage you to.

 

  1. public class AutoIncrementTask : Task
  2. {
  3.     private const string VersionPattern = @"\[assembly: AssemblyFileVersion\(\""(\d{1}).(\d{1}).(\d{1,}).(\d{6})""\)\]";
  4.     public string AssemblyInfoPath { get; set; }
  5.         
  6.     public override bool Execute()
  7.     {
  8.         try
  9.         {
  10.             if (String.IsNullOrEmpty(AssemblyInfoPath))
  11.                 throw new ArgumentException("AssemblyInfoPath must have a value");
  12.  
  13.             string[] content = File.ReadAllLines(AssemblyInfoPath, Encoding.Default);
  14.             var rx = new Regex(VersionPattern);
  15.  
  16.             var newContent = new List<string>();
  17.             content.ToList().ForEach(line =>
  18.                                             {
  19.                                                 if (rx.IsMatch(line))
  20.                                                     line = VersionMatcher(rx.Match(line));
  21.                                                 newContent.Add(line);
  22.                                             });
  23.  
  24.             File.WriteAllLines(AssemblyInfoPath, newContent);
  25.  
  26.         }
  27.         catch(Exception ex)
  28.         {
  29.             Console.Out.WriteLine(ex);
  30.             return false;
  31.         }
  32.  
  33.         return true;
  34.     }
  35.  
  36.     private string VersionMatcher(Match match)
  37.     {            
  38.         int major = int.Parse(match.Groups[1].Value);
  39.         int minor = int.Parse(match.Groups[2].Value);
  40.         int build = int.Parse(match.Groups[3].Value);
  41.         string revision = match.Groups[4].Value;
  42.  
  43.         Console.WriteLine("AutoIncrement Assembly {0}", Path.GetFileName(AssemblyInfoPath));
  44.         Console.WriteLine("Current matched version: {0}.{1}.{2}.{3}", major, minor, build, revision);
  45.  
  46.         ++build;
  47.         revision = String.Format("{0}{1}{2}", DateTime.Now.Year.ToString().Substring(2), String.Format("{0:d2}", DateTime.Today.Month), String.Format("{0:d2}", DateTime.Today.Day));
  48.         Console.WriteLine("Incremented to version: {0}.{1}.{2}.{3}", major, minor, build, revision);
  49.  
  50.         string result = match.Result("[assembly: AssemblyFileVersion(\"$1.$2.{0}.{1}\")]");
  51.         return String.Format(result, build, revision);
  52.     }
  53. }

And here is the corresponding xml MSBUILD file:

<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="4.0" DefaultTargets="IncrementBuild" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <UsingTask AssemblyFile="PATH_TO_TASK_DLL" TaskName="AutoIncrementTask" />
  <Target Name="IncrementBuild">
    <AutoIncrementTask AssemblyInfoPath="..\SharedAssemblyInfo.cs" />
  </Target>
</Project>

As you can see, I chose the AssemblyFileVersion as the target for custom product and assembly versioning because there are no compile time checks on the the format of the version and because a product version is more end-user and business stakeholder friendly than the automatic build numbers used internally by the .NET framework.

You can include the previous build task as a step in the build process capitalizing on the MSBUILD command line capabilities.

Hope this helped…

Stay #

Saturday, July 9, 2011

You “Try”… and what do you “Catch”… A TryCatchException!

This is posted without much ranting, hoping that the humour and the pun is evident and the code snippet self-explanatory. This code was written by someone who apparently regarded the try{} catch {} construct itself error prone and decided to catch a TryCatchException.

try
{
    //Some Magic Code here
}
catch (Exception ex)
{
    var exceptionEntry = new TryCatchException("Method error", ex);
    throw exceptionEntry;
}

I have to admit this one is an original. I particularly like the additional detail (that is completely useless) “Method error”


Code Responsibly.