A couple of days ago someone asked me how to export the areas and iterations from one project and be able to use them as a template to create other projects.  Creating a set of pre-defined Areas & Iterations is a feature of the TFS process templates.  In this post I've included a sample to show how to export the Areas and Iterations of an existing project into the format required for the Project Creation Wizard to use.

It is a command line tool with usage of the following form:

ExportClassifications /server:<yourserver> <yourproject>

This will create a file called Classification.xml that contains properly formatted XML for the Project Creation Wizard to use.

The only things that remain are

  • Export your Process Template using Team -> Team Foundation Server Settings -> Process Template Manager
  • Replace your the Classifications\Classifications.xml with the one generated by ExportClassifications
  • Use Process Template Manager to upload the updated Process Template
  • Start creating projects

I've attached the full sample project and a compiled version of the exe to this post for those who want it.  I've also included here the "heart" of the code that does the real work if you're just intersted in the API mechanics.

    // Connect to the server.
    TeamFoundationServer tfs = new TeamFoundationServer(server);

    // Get the common structure interface.
    ICommonStructureService css = (ICommonStructureService)tfs.GetService(typeof(ICommonStructureService));

    // Get the project we want to operate on.
    ProjectInfo projectInfo = css.GetProjectFromName(project);

    // Create the XML document that we are going to write the areas and iterations to.
    XmlDocument doc = new XmlDocument();
    doc.AppendChild(doc.CreateXmlDeclaration("1.0", "utf-8", null));

    // Create the tasks top level node.
    XmlNode parent = doc.CreateNode(XmlNodeType.Element, "tasks", String.Empty);
    doc.AppendChild(parent);

    // Create the node for the CommonStructureService task.
    XmlNode child = doc.CreateNode(XmlNodeType.Element, "task", String.Empty);
    AddAttribute(doc, child, "id", "UploadStructure");
    AddAttribute(doc, child, "name", "Creating project structure");
    AddAttribute(doc, child, "plugin", "Microsoft.ProjectCreationWizard.Classification");
    AddAttribute(doc, child, "completionMessage", "Team project structure created.");
    parent.AppendChild(child);
    parent = child;

    // Create the node to contain the data for the CommonStructureService task.
    child = doc.CreateNode(XmlNodeType.Element, "taskXml", String.Empty);
    parent.AppendChild(child);
    parent = child;
    XmlNode taskXmlNode = child;

    // Create the container for the root level CSS heirarchy nodes.
    child = doc.CreateNode(XmlNodeType.Element, "Nodes", String.Empty);
    parent.AppendChild(child);
    parent = child;

    // Get the list of heirarchies from the server.
    NodeInfo[] nodes = css.ListStructures(projectInfo.Uri);
    foreach (NodeInfo node in nodes)
    {
        // Handle the root nodes in the hierarchy specially because they have slightly different
        // naming and attribute handling.
        String name;
        if (node.StructureType == "ProjectModelHierarchy")
        {
            name = "Area";
        }
        else
        {
            name = "Iteration";
        }
        child = doc.CreateNode(XmlNodeType.Element, "Node", String.Empty);
        AddAttribute(doc, child, "StructureType", node.StructureType);
        AddAttribute(doc, child, "Name", name);
        AddAttribute(doc, child, "xmlns", String.Empty);
        parent.AppendChild(child);

        // Get the XML for this CSS Hierarchy.
        XmlElement parentXmlNode = css.GetNodesXml(new String[] { node.Uri }, true);

        // Skip down the hierarchy past the root node (which contains the same data as in the
        // NodeInfo that we got with ListStructures).
        XmlNode inNode = parentXmlNode.ChildNodes[0];
        if (inNode.ChildNodes.Count > 0)
        {
            inNode = inNode.ChildNodes[0];
            WriteNodes(doc, child, inNode.ChildNodes);
        }
    }

    // Write the reference to the project mapping file.
    child = doc.CreateNode(XmlNodeType.Element, "properties", String.Empty);
    taskXmlNode.AppendChild(child);
    parent = child;
    child = doc.CreateNode(XmlNodeType.Element, "property", String.Empty);
    AddAttribute(doc, child, "name", "MSPROJ");
    AddAttribute(doc, child, "value", @"Classification\FileMapping.xml");
    AddAttribute(doc, child, "isFile", "true");
    parent.AppendChild(child);

Brian