Category Archives: 1518

Download: Visual Studio 2010 Project Template for TFS Utilities

If you develop small utilities for Team Foundation Server a lot, you might want to save some time and use a project template (see bottom of post for download link) that already comes equipped with the correct references to the Team Foundation Object Model (Microsoft.TeamFoundation.*.dlls) as well as the most important using statements and a few lines of code to get started.

Installation

Copy the ZIP file to {MyDocuments}\Visual Studio 2010\Templates\ProjectTemplates.

Usage

Create a new project and select “TFS Utility” from the “Visual C#” list.

TFS Utility Project Template 

The template creates a new Windows Forms application with references to the Microsoft.TeamFoundation.*.dlls (btw: the C# compiler gets rid of all references that were not used in the project during compilation)…

 References to Team Foundation Object Model

… as well as a a few using statements and some code to start from.

Generated code in Form1.cs 

Happy TFS tool development!

Download: TfsUtility.zip

Download: Visual Studio 2008 Project Template for TFS Utilities

If you develop small utilities for Team Foundation Server a lot you might want to save some time and use a project template (see bottom for file attachment) that already comes equipped with the correct references to the Team Foundation Object Model (Microsoft.TeamFoundation.*.dlls) as well as the most important using statements and a few lines of code to get started.

Installation

Copy the ZIP file to {MyDocuments}\Visual Studio 2008\Templates\ProjectTemplates.

Usage

Create a new project and select “TFS Utility” from the “My Templates” list.

TFS Utility Project Template

The template creates a new Windows Forms application with references to the Microsoft.TeamFoundation.*.dlls (btw: the C# compiler gets rid of all references that were not used in the project during compilation)…

References to Team Foundation Object Model 

… as well as a a few using statements and some code to start from.

Generated code in Form1.cs

Happy TFS tool development!

 

Download: TfsUtility.zip

Update (Nov 13, 2011): There is an updated version available for VS 2010.

Using rich HTML descriptions instead of plain text

Objective

Allow rich HTML formatting in description fields of the MSF Agile process template.

Note: The MSF CMMI process does support HTML formatting by default. In order to use it you have to enable the formatting toolbar (see Step 6 below).

Work Item Customization

Step 1: Add a new HTML description field

Since the System.Description field is defined of type string as opposed to type HTML we need to create a new field:

2AddNewField

3AddNewField

Step 2: Change the work item layout

Use your own HTML field instead of System.Description

4EditLayout

Step 3: Refresh Work Item cache

Right-click "Work Items" in Team Explorer and select "Refresh".

5RefreshWIs

Step 4: Enable the formatting toolbar

Right-click on the Visual Studio toolbar, find and click "Formatting":

6EnableFormattingToolbar

A new toolbar will appear:

7FormattingToolbar

Result

Click into the description field and use the toolbar to format your input:

8UsingRichFormatting

 

Optional Step 5: Copying the old descriptions to the new HTML field

It would be a pity to loose the existing descriptions so let’s write a small utility using the Team Foundation Object model to copy the "old" descriptions to the new HTML field:

static void CopyOldDescriptions()
{
    // TODO: Change these values:
    string tfsName = "servertogo";
    string tfsProjectName = "WorkItemCustomization";
    string tfsHtmlDescriptionFieldName = "DescriptionHtml";
    string tfsWorkItemType = "Task";

    using (TeamFoundationServer tfs = TeamFoundationServerFactory.GetServer(tfsName))
    {
        WorkItemStore wit = (WorkItemStore)tfs.GetService(typeof(WorkItemStore));
        WorkItemCollection result = wit.Query(String.Format("SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject] = '{0}' AND [System.WorkItemType] = '{1}'", tfsProjectName, tfsWorkItemType));
        List<WorkItem> affectedWorkItems = new List<WorkItem>();
        foreach (WorkItem wi in result)
        {
            if (wi.Description.Length > 0)
            {
                // Set new description
                string value = (string)wi[tfsHtmlDescriptionFieldName];
                if (String.IsNullOrEmpty(value))
                {
                    wi[tfsHtmlDescriptionFieldName] = wi.Description.Replace("\n", "<br>");
                }
                else
                {
                    wi[tfsHtmlDescriptionFieldName] += "<br><p>Old description:</p><p>" + wi.Description.Replace("\n", "<br>") + "</p>";
                }

                // Delete old description
                wi.Description = String.Empty;

                affectedWorkItems.Add(wi);
            }
        }

        if (affectedWorkItems.Count > 0)
        {
            wit.BatchSave(affectedWorkItems.ToArray());
            MessageBox.Show("Items updated: " + affectedWorkItems.Count);
        }
        else
        {
            MessageBox.Show("Nothing to do.");
        }
    }
}


Happy formatting. :-)



 



Documentation: Team Foundation Server SDK (online version)

From the contents:

  • Team Foundation Server Extensibility
  • Team Foundation Server SDK Architecture
  • How to: Run Team Foundation Server SDK Samples
  • Team Foundation Core Services
  • Work Item Tracking Extensibility
  • Source Control Extensibility
  • Data Warehouse Extensibility
  • Reference for Team Foundation Server SDK

Link: http://msdn2.microsoft.com/en-us/library/bb130146(VS.80).aspx

Copy area and interation structure using the Area Import/Export Tool

If you look for a way to export and import your area and/or iteration structure the Team Foundation Object Model (TFOM) is your friend.

However it’s only your friend if you know where to look for.

While the export works perfectly using the WorkItemStore, the import is only possible through the ICommonStructureService (and could be used for export as well).

At the bottom you can download the source code of TFS Area Import/Export Tool.

TFSAreaImportExportTool

It saves your area and/or iteration structure into a text file and lets you import it into another project (even on another Team Foundation Server).

Feedback is appreciated.

Version 1.0.2 – compiled against Team Explorer 2010

Version 1.0.1 – compiled against Team Explorer 2008
File Attachment: AreaImportExportTool_1.0.1.zip (25 KB)

Version 1.0.0 – compiled against Team Explorer 2005
File Attachment: AreaImportExportTool.zip (69 KB)

Download: Visual Studio 2005 Project Template for TFS Utilities

If you develop small utilities for Team Foundation Server a lot you might want to save some time and use a project template (see bottom for file attachment) that already comes equipped with the correct references to all Microsoft.TeamFoundation.*.dlls as well as the most important using statements and a few lines of code to get started.

Installation

Copy the ZIP file to {MyDocuments}\Visual Studio 2005\Templates\ProjectTemplates.

Usage

Create a new project and select “TFS Utility” from the “My Templates” list.

TfsUtilityProjectTemplate1

The template creates a new Windows Forms application with references to the Microsoft.TeamFoundation.*.dlls (btw: the C# compiler gets rid of all references that were not used in the project during compilation)…

TfsUtilityProjectTemplate2

… as well as a a few using statements and some code to start from.

TFS_Utility

Happy TFS tool development!

File Attachment: TFS Utility.zip (16 KB)

Update (Nov 13, 2011): There are updated versions available for VS 2008 and VS 2010.

Getting started using Custom Work Item Controls

Since Service Pack 1 [1] we have the ability to create our own controls to display field value within a work item form which gives us great flexibility.


However there are two caveats with custom work item controls right now that aren’t solved:



  • They do not work with Web Access [2] so it’s not a choice for people that heavily rely on the web client.
  • They need to be deployed to the machine of every user accessing TFS.


Setting the stage


As an first realistic example we could make the priority field a little prettier. I mean the allowed values “1”, “2”, and “3” are not very descriptive. We don’t want to create a new field or change the values since we used this field already. So the solution would be to create a custom work item control on top of the existing values that displays something else.


I plan to create a new control that has a combobox on it and will display something nicer than the real values that are stored in the database. The complete source code is attached for reference.


1. Create the Work Item Control


A custom work item control is essentially a regular Windows Forms control. It has to derive from Control and implement IWorkItemControl.


The loading takes place in IWorkItemControl.InvalidateDatasource, the saving in IWorkItemControl.FlushToDatasource. The bold code indicates peaces that were necessary to implement my wishes. The rest is infrastructure and is repeated for every control you’ll write.


Here’s the code:


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Microsoft.TeamFoundation.WorkItemTracking.Controls;
using Microsoft.TeamFoundation.WorkItemTracking.Client;

namespace TeamSystemPro.Samples.WorkItemControls
{
    /// 
    /// Work Item Control for displaying the priority (can be 1,2, or 3 in MSF) in a more descriptive way then just showing the numbers.
    /// 
    /// 
    /// Custom controls need to derive from Control.
    /// Typically custom controls are built from UserControl.
    /// The control needs to implement IWorkItemControl.
    /// This is defined in Microsoft.TeamFoundation.WorkItemTracking.Controls.dll assembly that can be found from VS installation folder, typically ":\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies".
    /// Add reference to that assembly and line "using Microsoft.TeamFoundation.WorkItemTracking.Controls;" in code.  
    /// How it works:
    ///   After the control is loaded, a reference to work item is passed to the control using IWorkItemControl.WorkItemDatasource property.
    ///   The control is asked to display its data using IWorkItemControl.InvalidateDatasource method.
    ///   The control is required to update any values directly in WorkItem object itself when user changes data. 
    /// 
    public partial class PriorityControl : UserControl, IWorkItemControl
    {
        private WorkItem workItem;
        private string workItemFieldName;
        private IServiceProvider serviceProvider;
        private System.Collections.Specialized.StringDictionary properties;
        private bool readOnly = false;

        public PriorityControl()
        {
            InitializeComponent();
        }

        #region IWorkItemControl Members

        /// 
        /// Raise this events before updating WorkItem object with values. When value is changed by a control, work item form asks all controls (except current control) to refresh their display values (by calling InvalidateDatasource) in case if affects other controls 
        /// 
        public event EventHandler BeforeUpdateDatasource;

        /// 
        /// Raise this event after updating WorkItem object with values. When value is changed by a control, work item form asks all controls (except current control) to refresh their display values (by calling InvalidateDatasource) in case if affects other controls 
        /// 
        public event EventHandler AfterUpdateDatasource;

        /// 
        /// Control is asked to clear its contents
        /// 
        void IWorkItemControl.Clear()
        {
            cboPriorities.SelectedIndex = -1;
        }

        /// 
        /// Control is requested to flush any data to workitem object. This usually happens during save operation or when the form is left. In most cases data will be written to workitem immediately on change and hence this will not need implementation. Some customers want a way to do operations during save, and this is the closest thing we got. If you do need a way to react to before-save & after-save events, pls let us know in forums given below and we'll consider for future revision.
        /// 
        void IWorkItemControl.FlushToDatasource()
        {
            this.BeforeUpdateDatasource(this, EventArgs.Empty);
            workItem.Fields[workItemFieldName].Value = Convert.ToString(cboPriorities.SelectedIndex + 1);
            this.AfterUpdateDatasource(this, EventArgs.Empty);
        }

        /// 
        /// Asks control to invalidate the contents and redraw. At this point, control can read from work item object and display/refresh data.
        /// 
        void IWorkItemControl.InvalidateDatasource()
        {
            if (IsInitialized())
            {
                int currentValue = (int)workItem.Fields[workItemFieldName].Value;
                cboPriorities.SelectedIndex = currentValue - 1;
            }
        }

        /// 
        /// A property bag of all attributes specified in work item form xml for this control. Custom attributes are allowed and can be used to pass parameters specific for this control from work item type xml.
        /// 
        System.Collections.Specialized.StringDictionary IWorkItemControl.Properties
        {
            get { return properties; }
            set { properties = value; }
        }

        /// 
        /// Tells the control to display in readonly mode.
        /// 
        bool IWorkItemControl.ReadOnly
        {
            get { return readOnly; }
            set { readOnly = value; OnReadOnlyChanged(); }
} /// /// Gives pointer to IServiceProvider if you intended to access Document service or VS Services. If services are not needed, do nothing in this method. /// /// void IWorkItemControl.SetSite(IServiceProvider serviceProvider) { this.serviceProvider = serviceProvider; } /// /// This passes reference to source work item object. Cast this object to WorkItem type. /// object IWorkItemControl.WorkItemDatasource { get { return workItem; } set { workItem = value as WorkItem; } } /// /// The field name if the control is associated with a field name in work item form xml. A custom control can be associated with 0 or 1 work item field. /// string IWorkItemControl.WorkItemFieldName { get { return workItemFieldName; } set { workItemFieldName = value; } } #endregion private bool IsInitialized() { return (!this.IsDisposed && workItem != null && !string.IsNullOrEmpty(workItemFieldName) && workItem.Fields.Contains(workItemFieldName)); } private void OnReadOnlyChanged() { cboPriorities.Enabled = !readOnly; } } }

Additionally you need to create an XML file with the .wicc extensions which contains the name of your assembly file as well as the full-qualified name (i.e. namespace and classname) of your control class:


CustomWorkItemControls5


So you have your control as well as the .wicc-file (which is necessary for registration):


CustomWorkItemControls2


2. Deploy the Work Item Control


Although you could simply copy the two files (.dll and .wicc) to the “Microsoft\Team Foundation\Work Item Tracking\Custom Controls” under Environment.SpecialFolder.CommonApplicationData (we could also use the folder unter then under Environment.SpecialFolder.LocalApplicationData), but I decided to create a new MSI setup with Visual Studio which might look like this:


CustomWorkItemControls3


3. Reference the new control in a Work Item Type


After the control is deployed just change the type attribute for the control in the work item type XML. The Type should reference the name of the .wicc-file.


CustomWorkItemControls4


Now you can import your modified work item type XML (you need to use witimport as the Process Template Editor does not support custom controls right now), refresh the cache by right-clicking the Work Items node in Team Explorer and press “Refresh”.


CustomWorkItemControls1


Further recommended reading:


  • How to use Custom Controls in Work Item Form [3]
  • Communicating between custom controls: Building parent/child controls [4]

Enjoy increasing your Work Item UI experience through custom controls!


-Neno


[1] http://msmvps.com/blogs/vstsblog/archive/2006/12/15/download-visual-studio-2005-team-suite-team-foundation-server-service-pack-1-sp1.aspx


[2] http://www.devbiz.com


[3] http://blogs.msdn.com/narend/archive/2006/10/02/How-to-use-Custom-Controls-in-Work-Item-Form.aspx


[4] http://blogs.msdn.com/narend/archive/2006/10/19/communicating-between-custom-controls-building-parent-child-controls.aspx


File Attachment: WorkItemCustomControlDemo.zip (25 KB)

How Do I: Customize TeamPlain? and How Do I: Create Custom Work Items in Team Foundation Server?

What do both topics have in common? Well, Microsoft started to publish How-Do-I-videos for various technologies and these two were the same topics covered on Visual Studio Team System.


  • How Do I: Customize TeamPlain?

    In this video, Scott Golightly shows you how you can customize TeamPlain Web Access to work the way that you do. You will see how to create and assign work items, create your own queries, and how to create and customize favorites to make navigation in the product easier.

 


  • How Do I: Create Custom Work Items in Team Foundation Server?

    In this video, Scott Golightly shows us how to use the Visual Studio 2005 Team Foundation Server Power Tools to create custom work items. He shows how to add additional fields to the bug work item type and how to display the new fields in the bug entry form.

 


 


Notification for new videos


You can also subscribe to the Team System video category by adding this feed to your favorite RSS feed reader.

Validation error when saving Work Items after a user is removed from Active Directory

Problem: If you remove a user from Active Directory or the local machine (depending where you store your user accounts for TFS), all work items that were assigned to that user cannot be modified anymore, at least if you use the default MSF process templates.


The following validation error appears that requires the value in the “Assigned To” field to be a valid user:


Image-0009b


Workaround 1 (easiest): Just reassign the bug to yourself or someone else. Caveat: You probably don’t want to do that because the information is then not correct anymore since it was not you working on the work item.


Workaround 2 (recommended): You can modify the Work Item Type definitions so that the “Assigned to” field does not re-validate values that have been successfully validated in the past. In this case there would be not error, however if you put in a new name into the “Assigned to” field it would be validated.


  1. Export the WIT (Work Item Type) of which you want to change the behavior as described using the Microsoft Process Editor.
  2. Add the ALLOWEXISTINGVALUE rule to the field definition of the “Assigned to” field.

    Image-0021
  3. Save and import the WIT into your team projects and you’re ready to go.

Note: Be aware that you need to change all Work Item Types and for all team project separately where you want the new behavior to be used.


-Neno