As a matter of self-inflicted education I’ve decided to create a simple Visual Studio Add-In for exporting and importing Areas and Iterations. I’m not sure how much practical use such a utility will receive but it offers several areas for advancing my knowledge and, hopefully, helping a few other people out along the way.
Although I haven’t completed the utility yet, I have completed some of the initial utility code. I thought I would create a few posts as I progress in case anyone can make use of the examples. For this post, I am posting the code used to retrieve the list of “areas” from a Team Foundation Server.
With that said, here is some example code for saving the list of Areas defined for a given Team Foundation Server and Team Project. The code is a little verbose but should be relatively simple to follow.
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Server;
namespace TestConsole
{
public class ExportAreas
{
private TeamFoundationServer _teamFoundationServer;
private ICommonStructureService _commonStructureService;
///
///
/// The team foundation server. /// The name of the team project to export areas from. /// The filename to save the exported areas to. public void Export(string teamFoundationServer, string projectName, string filename)
{
_teamFoundationServer = TeamFoundationServerFactory.GetServer(teamFoundationServer);
_commonStructureService = (ICommonStructureService)_teamFoundationServer.GetService(typeof(ICommonStructureService));
List<HierarchyNode> nodeList = new List<HierarchyNode>();
// Locate root structure node for “Area”
NodeInfo areaNode = GetAreaRootNode(projectName);
//String node = _commonStructureService.CreateNode(“TEST Node…”, areaUri);
// Retrieve the Area nodes XML
XmlElement nodes = _commonStructureService.GetNodesXml(new string[] { areaNode.Uri }, true);
// Recursively build out the list of Area nodes
BuildHierarchicalList(nodes.ChildNodes[0], nodeList, 0);
// Save the areas to the designated text file
StreamWriter writer = new StreamWriter(filename, false);
foreach (HierarchyNode node in nodeList)
{
writer.WriteLine(new string(‘\t’, node.IndentLevel) + node.Name);
}
writer.Close();
}
///
///
/// The root node to start with. /// The target list to add each
/// list must be instantaited on the first call. /// The indent level – pass in 0 for the initial call. private void BuildHierarchicalList(XmlNode rootNode, List<HierarchyNode> targetList, int indentLevel)
{
HierarchyNode listNode;
if (rootNode.Name == “Children”)
{
for (int index = 0; index < rootNode.ChildNodes.Count; index++)
{
BuildHierarchicalList(rootNode.ChildNodes[index], targetList, indentLevel);
}
}
else
{
listNode = new HierarchyNode()
{
Uri = rootNode.Attributes[“NodeID”].Value,
Name = rootNode.Attributes[“Name”].Value,
ParentUri = GetAttribute(rootNode, “ParentID”),
Path = rootNode.Attributes[“Path”].Value,
ProjectUri = rootNode.Attributes[“ProjectID”].Value,
StructureType = rootNode.Attributes[“StructureType”].Value,
IndentLevel = indentLevel
};
targetList.Add(listNode);
if (rootNode.HasChildNodes)
{
for (int index = 0; index < rootNode.ChildNodes.Count; index++)
{
BuildHierarchicalList(rootNode.ChildNodes[index], targetList, indentLevel + 1);
}
}
}
}
///
///
/// The node containing the attribute collection. /// The name of the attribute to retrieve. ///
private string GetAttribute(XmlNode node, string attributeName)
{
for (int index = 0; index < node.Attributes.Count; index++)
{
if (string.Equals(node.Attributes[index].Name, attributeName, StringComparison.InvariantCultureIgnoreCase))
{
return node.Attributes[index].Value;
}
}
return string.Empty;
}
///
///
/// The name of the team project to retrieve the root node from. ///
private NodeInfo GetAreaRootNode(string projectName)
{
ProjectInfo projectInfo = _commonStructureService.GetProjectFromName(projectName);
return LocateStructureByType(projectInfo.Uri, “ProjectModelHierarchy”);
}
///
///
/// The project URI to retrieve the structure from. /// Type of the structure to retrieve. ///
private NodeInfo LocateStructureByType(String projectUri, String structureType)
{
NodeInfo[] nodes = _commonStructureService.ListStructures(projectUri);
foreach (NodeInfo node in nodes)
{
if (node.StructureType == structureType)
{
return node;
}
}
return null;
}
}
///
///
class HierarchyNode
{
public string Uri { get; set; }
public string Name { get; set; }
public string ParentUri { get; set; }
public string Path { get; set; }
public string ProjectUri { get; set; }
public string StructureType { get; set; }
public int IndentLevel { get; set; }
}
}
To use the above sample code, just instantiate the ExportAreas class and call the Export method passing in the desired argument values.
Jeff,
Have a look at this tool
http://msmvps.com/blogs/vstsblog/archive/2007/07/07/copy-area-and-interation-structure-using-the-area-import-export-tool.aspx
Eugene, thanks for the link. I’ve seen other examples regarding Areas and Iterations as well. This exercise is basically an excuse to create a simple TFS utility and provide integration with Visual Studio as an add-in. I realize I’m re-inventing the wheel (to a certain extent) but it seems like a great way to sharpen some skills :-)