Search This Blog

Thursday, December 27, 2007

VersionControlPath - Class to Manipulate Version Control Items Path

I was navigating through TFS assemblies and I found out a static class that I wasn't aware of: Microsoft.TeamFoundation.VersionControl.Common.VersionControlPath. This class contains functions that help manipulating version control items path. It is like the System.IO.Path class. Here are some of the methods in the class:
  • GetFileName
  • GetExtension
  • GetFolderDepth
  • Combine
  • GetFolderName
  • ValidatePath

Very useful.

Monday, December 24, 2007

No matching items found in {0} at the specified version

I recently got this error while trying to create a branch from that its parent was renamed.

Here's an example of what happened:

  1. A branch was created at: $/Project/Folder1/Branch1.
  2. Some work has been done on Branch1 so its history contained several change sets.
  3. Folder1 was renamed to Folder2 ($/Project/Folder2/Branch1).
  4. A branch operation failed while trying to create one from a change set before the rename operation with the error: "No matching items found in $/Project/Folder2/Branch1" (A branch operation on a change set created later than the rename operation will succeed).

I thought that the rename operation has broken the branch history. Looking at the branch dialog I saw that the source branch text box is read only and I thought to myself what would have happen if I had changed the source from $/Project/Folder2/Branch1 to $/Project/Folder1/Branch1. It was time for some coding…

private void PerformBranch(string server, string workspaceName, string userName, string changesetId, string sourceBranch, string targetBranch)

TeamFoundationServer tfs = new TeamFoundationServer(server);
VersionControlServer vcs = tfs.GetService(typeof(VersionControlServer)) as VersionControlServer;
Workspace workspace = vcs.GetWorkspace(server, userName);
VersionSpec versionSpec = VersionSpec.ParseSingleSpec(changesetId, userName);
workspace.PendBranch(sourceBranch, targetBranch, versionSpec);

This method has fixed the problem and after running it with the old branch path (source = $/Project/Folder1/Branch1), pending changes were waiting for check in.

Thursday, December 06, 2007

TF20015: The field 'xxx' contains a value that is not in the list of supported values.

While trying to save a work item in TFS you might be facing a problem doing it when the error TF20015 is raised. This error is raised when you are trying to enter values that are not part of the allowed values of the field. The strange thing is that it can happen although the value was already saved before to the work item and the field is disabled. As a result you cannot change the value and therefor cannot save the work item. So why does it happen? I faced this problem in two cases:

  1. The user in one of the fields (which is implementing the valid user value list as the allowed values for the field) was renamed or deleted.

  2. The work item schema was changed in a way that made some of the existing work items have illegal values. For example, if you made one of the fields mandatory trough all of the work flow and you have some work items with a null value in the field.

So, how can you fix it?

There are 2 ways to do it:

  1. Changing the work item schema temporarily so the field won't be disabled and then you can change the value.

  2. Write some code the change the field value:

Here's a code sample on how to update work item field values:

public void UpdateWorkItem(string serverUri, int id, string fieldName, string fieldValue)
TeamFoundationServer tfs = new TeamFoundationServer(serverUri);
WorkItemStore wis = tfs.GetService(typeof(WorkItemStore)) as WorkItemStore;
WorkItem workItem = wis.GetWorkItem(id);
workItem.Fields[fieldName].Value = fieldValue;

Monday, December 03, 2007

Set Work Item Type field allowed values when another field value changes

I was asked once by a friend if there's a way to filter the allowed values of a field when another field value changes. Well, the solution is not exactly as we think about filtering but more like a switch/case mechanism.

Let's take for example 2 fields that implement OS Platform & Version selection:

Windows --> XP, 2003 Server, Vista

Linux --> Ubuntu, Red Hat, Suse

Mac --> OS X 10.0, OS X 10.5

To implement this in the work item type definition file we need to define 2 fields. The xml should look like this:

name="OS Platform"


value="Windows" />

value="Linux" />

value="Mac" />



name="OS Version"



value="XP" />

value="2003 Server" />

value="Vista" />





value="Ubuntu" />

value="Red Hat" />

value="Suse" />





value="OS X 10.0" />

value="OS X 10.5" />




The version field contains WHEN rule for each platform. The result is a field that changes in real time when the parent field value changes.

You don't have to write the xml in order to achieve this. You can use the "Process Template Editor" which is part of the Team Foundation Server power tools to easily add fields and rules to you work item.

Thursday, November 29, 2007


I have a new project in CodePlex named TFSQueryExplorer. It is a Visual Studio addin that looks like the Team Explorer tool window but it is dedicated to the management of queries and work items. There are a lot of cool features like manage queries in tags/folders, quick search, integration with the work item templates power tool and so on. The project is an example for using Visual Studio SDK and Team System API. I hope that you'll find it useful.

Sunday, October 21, 2007

Could not load file or assembly 'Microsoft.Data.ConnectionUI' or one of its dependencies - Visual Studio 2005 SDK

I have noticed that after installing Visual Studio 2005 SDK one of my web projects has stopped running in Visual Studio raising an exception that says: "Could not load file or assembly 'Microsoft.Data.ConnectionUI' or one of its dependencies". After some investigation I have found that the file exists also under the common assemblies directory of the SDK (C:\Program Files\Visual Studio 2005 SDK\2007.02\VisualStudioIntegration\Common\Assemblies) and somehow although I do not use the assembly it is copied as a reference. The solution for that was deleting the file from the SDK common assemblies folder (since it is already contained in the framework). After the first deletion I made I had to delete another assembly from that folder and the project was running again.

Wednesday, October 10, 2007

Keyboard Language On Login Screen Not Set To Default

When installing windows with default language not set to english and changing it after installation you will notice that on the login screen the language is set to the language selected during installation. To change it english you need to edit the registry key HKEY_USERS\.DEFAULT\Keyboard Layout\Preload. In this key you will find probably 2 values named 1 and 2. You need to switch between the values so that the value named 1 will be set to 00000409 which is english. It happens to me when I get a new computer that is from a specific vendor and the OS is already installed.

Saturday, September 15, 2007

Team Build 2008 API

I have installed Team Foundation Server 2008 Beta 2 on my staging environment this week. The installation process was smooth and except for some small issues I could start testing the release after a simple installation process.

Naturally, the first thing I have checked was the Team Build new features. I will not expand in the words regarding the new features because there are already some posts describing it ( Anyway, some of the new features ease the management of the builds from the UI (Delete, Open Drop Folder…) and were available in Team Foundation Server 2005 using 3rdParty tools (TFSBuildManager). What I like the most is the Drop Management feature that completes the Continuous Integration feature. By using the retention policy of a build definition (Build Type is now Build Definition) you can define what and how to save builds. Builds can also be marked as save forever which can be useful when you want to mark a build that was released to a customer.

The second thing that I have checked was the new Team Build object model in this version. Since I'm a heavy consumer of the Team Build API I was curious to find out how it looks. For the record, TFSBuildManager works on Team Foundation Server 2008 (some of the interfaces became obsolete so I would probably have to work on a new version).

The first thing I have noticed is that the BuildStore interface became obsolete and it is replaced with the IBuildServer interface. So, in order to create an instance of the interface we need to do the following:

TeamFoundationServer tfs = new TeamFoundationServer("ServerName");


IBuildServer bs = (IBuildServer)tfs.GetService(typeof(IBuildServer));

In Team Foundation Server 2005 there was no interface to manage Build Type. If you wanted to query the server build types you needed to use the Version Control API to get the list of branches under the $/ProjectName/TeamBuildTypes branch. In 2008 the term Build Type is replaced with Build Definition. There is also a new interface to manage it named IBuildDefinition. Here's an example of how to get the list of build definitions for a project:

IBuildDefinition[] buildDefinitions = bs.QueryBuildDefinitions("ProjectName");

Another interface that became obsolete is the BuildData interface. Instead of using this interface we now have a new one named IBuildDetail. The following example shows the replacement for the method GetListOfBuilds that was available in 2005:

IBuildDetail[] buildDetails = bs.QueryBuilds("ProjectName");

The IBuildDetail interface is wider than the BuildData interface and it's in parallel to the big changes made to Team Build in 2008. Some of the new members we can use are:

  • SourceGetVersion – A string that represents the version control source version for the build.
  • KeepForever – A Boolean value that marks a build as one that won't be deleted while applying the retention policy.
  • LabelName – A string value that represents the version control label of the build.
  • CompilationStatus, TestStatus – A BuildPhaseStatus value that represent the phase status (Failed, Succeeded, Unknown).

One of the big changes in Team Build 2008 is the build agents. In 2005 build machines were related to a specific build type. In 2008, with the builds queue feature, you don't have to relate a build server to a specific build definition. Build servers are now treated as agents and can serve all build definitions. For each Build Definition you specify a default build agent. The build agent is represented through the IBuildAgent interface that was already available in 2005 but only for executing a build.

To get the list of build agents we need to do the following:

IBuildAgent[] buildAgents = bs. QueryBuildAgents("ProjectName");

To create a new build agent:

IBuildAgent buildAgent = bs. CreateBuildAgent("ProjectName");

buildAgent.MachineName = "BuildMachineName";

buildAgent.Name = "BuildAgentName";

buildAgent.BuildDirectory = @"C:\BuildDirectory";

buildAgent.Port = 9191;


There are some more properties to set for creating a new build agent but these are the required ones.

Starting a build is a little different too. Since we do not start a build but queue a build we need to use the QueueBuild method in the IBuildServer interface.

IBuildDefinition buildDefinition = bs. GetBuildDefinition("ProjectName", "BuildDefinitionName");


One thing I found missing in the current release API was the ability to edit build definition using the IProjectFile interface. The IProjectFile interface wraps the MSBuild project file but it is only available when creating a new build definition.

There is a lot more in the new Team Build API. I have tried to cover the basics in this post.

I hope I'll have some time soon to write the support for Team Build 2008 in TFSBuildManager. I already got some cool ideas using the new API.

Thursday, September 06, 2007

Filename Collision - Another item with the same name exists on the server.

At one of our merges we encountered an error saying that there is a file collision and we could not complete the process. The error is raised when you are performing the check in after the merge. The merge itself passes with no error. It seem that it happens when 2 files/folders with the same name and location are added to both branches. While performing the merge the source branch treats the new item as a branch action to the destination branch which results in adding the file in the check in process. The merge process does not check if the file already exists and when you perform the check in you get the error and the only option to resolve it is to delete the local file (the file from the merge action). The problem is that we wanted the file from the merge source branch. To fix this we needed to delete the file in the destination branch (after performing undo pending changes for the merge) and than perform the merge again.

Wednesday, September 05, 2007

Terminals Achievements

We are celebrating 2 major events in Terminals life. The first one is that latest release was downloaded 10,000 times. The second one and the sweetest is that the project page is the first result in Google's search for the word Terminals (Out of 37,000,00 pages!!!). This is a result of the posts written regarding the utility and the people that are using it. Thank you all.

We are working on a new version with lots of features and we added some guys to help us with the development. Hope we can deliver it soon. Enjoy.

Tuesday, August 28, 2007

Moving Team Foundation Server from a single-server deployment to a dual-server deployment

It's been a while since I've posted something. Shame on me!

The last weeked was dedicated to moving our Team Foundation Server from a single server deployment to a dual server deployment. I have already gone throught the process of moving a server from one hardware configuration to another so I was quite sure that this would work.

Our previous configuration was a virtual server on an IBM blade with 2GB memory serving about 50 users. We have decided to split the deployment and add a database server which is the number one consumer of resources.

I've started the process around 21:00 and finished at 02:30. The most problematic part was that for some reason I could not uninstall SQL Server and Visual Studio from the application sevrer (the new deployment requieres uninstall of current Team Foundation Server installation and installing as an application server). I had to use the windwos installer cleanup utility to remove them from windows installer database and then I reinstalled them to their previous state. After that again unistall and installing the Team Foundation Server application tier. You can imagine it took me sometime...

Some remarks regarding the document (How to: Move from a Single-Server to a Dual-Server Deployment):

  • In the section named To modify the Web.Config file to reflect the original Team Foundation data-tier server name: In 1.a there is a mistake when refering to the new data-tier server when locating the web.config file of the services. It should be the application-tier server.

  • In the section named To restore and verify Report Server on the new Team Foundation Server: In 17 you are suppose to execute SetupWarehouse.exe but it won't happen since the TFSAppPull is still down. SetupWarehouse.exe uses the web service to initilize the process of rebuilding the Team System OLAP cube. You need to execute it after you are restarting the services in the section named To restart services and verify operation.

Another problem I encountered was related to the databases restore. I must say that it was my mistake since I did not follow the process and restored the databases by detaching the new ones and attaching the old ones. The issue was that the 2 databases using full text search catalog (TfsWorkItemTracking and STS_Content_TFS) were attached with the wrong reference to the full text catalog. As a result the catalog could not be rebuilt and backups failed. In addition while searching work items using the Steps to Reproduce field (which is indexed in the catalog) an error raised specifing the query failed and there is a problem on the server.

I did some search using the errors I saw in the event viewer and in database logs and understood that the catalog needs to be rebuilt. When executing the rebuild using the management studio I got no error but the process ran for about 24 hours. I'm not a DBA but this seemed strange so I stopped it and continue searching using this keywords: "Full-Text Search is not enabled for the current database", "Property FullTextIndexSize is not available for FullTextCatalog" and with the names of the catalogs: ix_STS_Content_TFS and TeamFoundationServer10FullTextCatalog. I did not find much (except for this incomplete posts). Anyway, I understood that I have to drop and recreate the catalogs. After doing this the catalogs were rebuild and everything worked.

Here are the steps I took to recreate the catalogs.

Please notice that this part is done by the Team Foundation Server installation and I did this only because the catalogs were corrupted. If you are not familiar with this stuff I suggest you consult with a Team System advisor or try to reinstall the server. Any way don't forget to backup the database. Since in this case you have problem doing it because the corrupted catalogs disturb the backup I suggest you copy the data files (mdf and logs) to another location (after you stop the system...) or find a way to disable backing up the catalogs (I read about it some where).

Open Microsoft SQL Server Management Studio and connect to the Team Foundation Server database.

For recreating the ix_STS_Content_TFS catalog do the following:

  • In the object explorer expand: Databases --> STS_Content_TFS --> Storage and right click the ix_STS_Content_TFS catalog. Select Delete from the menu and press OK button in the Delete Object window. This will drop the corrupted catalog (if your catalog is corrupted you will see error when trying to open it's properties window).

Right click the Full Text Catalogs item and select New Full-Text Catalog... from the menu. In the New Full-Text Catalog - STS_Content_TFS enter the name of the catalog: ix_STS_Catalog_TFS, select a location for the files, select Primary in the Filegroup combo box and in the Owner text box select dbo. Press the OK button.
  • Double click the newly created catalog in the Object Explorer tree. In the Full-Text Catalog Properties - ix_STS_Content_TFS select the Tables/Views from the left list view. Add the tables: dbo.Docs, dbo.Lists, dbo.UserData and dbo.UserInfo to the Table/View objects assigned to the catalog and start setting the Eligible colums for the tables.
  • For dbo.Docs select the Content and LeafName. For both of them select the language English in the Language for Word Breaker setting column. For Content select Extension in the Data Type Column.
  • For the dbo.Lists table select the tp_Description and tp_Title columns. For both of them select the language English in the Language for Word Breaker setting column.
    • For the dbo.UserData table select all the columns except for tp_Ordering.

    • For the dbo.UserInfo table select the tp_Email, tp_Login and tp_Title columns. For all of them select English in the Language for Word Breaker setting column.
    • Press the OK button. The catalog should be processed for some time.

    For recreating the TeamFoundationServer10FullTextCatalog catalog do the following:

    • In the object explorer expand: Databases --> TfsWorkItemTracking --> Storage and right click the TeamFoundationServer10FullTextCatalog catalog. Select Delete from the menu and press OK button in the Delete Object window. This will drop the corrupted catalog.

    • Right click the Full Text Catalogs item and select New Full-Text Catalog... from the menu. In the New Full-Text Catalog - TfsWorkItemTracking enter the name of the catalog: TeamFoundationServer10FullTextCatalog, select a location for the files, select Primary in the Filegroup combo box and in the Owner text box select dbo. Check the Set as default catalog check box. Press the OK button.
    • Double click the newly created catalog in the Object Explorer tree. In the Full-Text Catalog Properties - TeamFoundationServer10FullTextCatalog select the Tables/Views from the left list view. Add the tables: dbo.WorkItemLongTexts to the Table/View objects assigned to the catalog. In the Eligible columns select the Words column and press the OK button. The catalog should be processed for some time and the window will be closed.

    That's it. The catalogs were created and you should be able to process them.

    Tuesday, July 17, 2007

    How to Expose the Work Item Editor Control

    I've used this while writing the Cropper TFS Work Item plugin. I needed a way to edit or create a new work item. The WorkItemFormControl located under the Microsoft.TeamFoundation.WorkItemTracking.Controls namespace is the same control used by Visual Studio work item plugin and also by the process template editor (which was the way I found how to use it).

    Here's an example for creating a new work item with the control.

    First we need to connect to a Team Foundation Server and obtain the WorkItemStore service:

    TeamFoundationServer tfs = new TeamFoundationServer(serverName);
    WorkItemStore wis = tfs.GetService(typeof(WorkItemStore)) as WorkItemStore;

    After doing so we can now create the WorkItemFormControl:

    WorkItemFormControl wifc = new WorkItemFormControl();

    The WorkItemFormControl has a string property named FormDefinition. We need to set this property with an XML defining the work item type that we want to use. To do so we use the WorkItemStore service:

    WorkItemType wit = wis.Projects[teamProjectName].WorkItemTypes["Bug"];

    This will return the the Bug work item type.

    After doing so we can use the WorkItemType to set the FormDefinition property:

    XmlDocument xmlDocument = wit.Export(false);
    wifc.FormDefinition = xmlDocument.InnerXml;

    Now we can use the WorkItemFormControl with a newly created work item or an existing one:

    WorkItem wi = new WorkItem("Bug"); or WorkItem wi = wis.GetWorkItem(bugId);
    wifc.Item = wi;

    To show the control embed it to a form or a panel on a form.

    Wednesday, June 06, 2007

    Wednesday, May 30, 2007

    Cropper TFS Work Item Plugin

    It's been a while since I wrote here. Anyway, I hope this post will compensate for it. I read this week a post about SnagIt! integration with TFS. Since I use Cropper I've decided to write a plugin for TFS.
    The plugin enables you to capture images directly to a new TFS work item attachments field. You can also add an attachment to an existing work item. You can download it from here. Read the read me file for installation guide and how to use it.
    The plugin uses the WorkItemFormControl to edit the work item. I will explain in future posts on how to use it.
    I'm planning to add the sources to Cropper Plugins project in CodePlex.
    The plugin is in it's early stages. I would be happy to hear your comments.

    Tuesday, April 17, 2007

    How to Get Build Result Details using TFS API - Part 3

    The previous post in this series was about the build steps section of the build report. In this post we will see how to retrieve the associated changesets section details.

    Using the BuildStore object we have created in this post we can get a list of ChangeSetData objects that contain the needed information (an example on how to get the buildUri parameter value available in this post also):

    ChangeSetData[] changesets = buildStore.GetChangeSetsForBuild(buildUri);

    foreach (ChangeSetData changeset in buildReport.Changesets)







    Thursday, April 12, 2007

    Extracting Images from Work Items Attachments

    In this example I will show how to use the WorkItemStore interface. This example will execute a stored query on the work items database and will extract the attachments from the work items returned from the query. This is a good training for working with the WorkItemStore interface.

    private void ExtractWorkItemsAttachments(string teamFoundationServer, string teamProject, string storedQuery,

    string saveTo)

    //Logon to the server and create the needed objects
    TeamFoundationServer tfs = TeamFoundationServerFactory.GetServer(teamFoundationServer);
    WorkItemStore store = (WorkItemStore)tfs.GetService(typeof(WorkItemStore));
    Project tfsProject = store.Projects[teamProject];
    StoredQueryCollection sqc = tfsProject.StoredQueries;
    string querystring;
    //Search for the query
    foreach (StoredQuery query in sqc)
    if (query.Name == storedQuery)
    //Execute the query
    querystring = query.QueryText;
    querystring = querystring.Replace("@project", "'" + tfsProject.Name + "'");
    WorkItemCollection workItems = store.Query(querystring);
    //Extract the attachments
    foreach (WorkItem workItem in workItems)
    if (workItem.Attachments.Count > 0)
    foreach (Attachment attachment in workItem.Attachments)
    //Using WebClient to download the attachment
    WebClient webClient = new WebClient();
    webClient.Credentials = CredentialCache.DefaultCredentials;
    string fileName = Path.Combine(saveTo, attachment.Name);
    webClient.DownloadFile(attachment.Uri.AbsoluteUri, fileName);

    Tuesday, April 10, 2007

    How to Get Build Result Details using TFS API - Part 2

    The previous post in this series was about the summary section of the build report. In this post we will see how to retrieve the build steps section details.
    Using the BuildStore object we have created in the previous post we can get a list of BuildStepData objects that contain the needed information (an example on how to get the buildUri parameter value available in the previous post also):

    BuildStepData[] buildSteps = buildStore.GetBuildSteps(buildUri);

    Now we can go through all the objects in the collection and retrieve details for each one of them.

    foreach (BuildStepData in buildSteps)

    Thursday, March 29, 2007

    How to Dock the Vista Toolbars to the Edge of the Screen

    I found a way to dock Vista toolbars to the edge of the screen since drag and drop does not work anymore:
    1) Create a new folder on the desktop
    2) Drag it to on of the edges so it would become a toolbar
    3) Right click the toolbar and select the toolbar that you want to show
    4) Now you can define the toolbar behaviour (Auto Hide, Alway on Top)

    Wednesday, March 14, 2007

    How to Get Build Result Details using TFS API - Part 1

    In this series of posts I would explain how to use TFS API in order to retrieve build result details as they appear in the build report.

    In order to retrieve result details for a build we need to create a BuildStore object. There is an example on how to create a BuildStore object on a previous post: Get Build Changes. The example take into consideration that you have already created the BuildStore object and it is named buildStore.

    In this post we will see how to retrive the details under the summary section of the build report. First, we need to get the BuildData object for the build. Here's how to get the BuildData object:

    BuildData buildData = buildStore.GetBuildDetails(buildStore.GetBuildUri(teamProject, buildNumber));

    Now that we've got the BuildData object we can retrieve the build details that appear in the summary section of the report:


    On the next post for this series I will explain how to retrieve the details for the "Build Steps" section of the report.

    Sunday, February 25, 2007

    Start a Team Build Using BuildProgressForm

    I found out another way for starting a build using the BuildProgressForm. The BuildProgressForm is the same one used by Visual Studio Team Build intergration for starting a build.

    This method is very useful for my tool TFSBuildManger.
    Here's an example of how to do so:

    BuildParameters buildParameters = new BuildParameters();
    buildParameters.TeamFoundationServer = teamFoundationServer; buildParameters.TeamProject = teamProject;
    buildParameters.BuildType = buildType;
    buildParameters.BuildMachine = buildmachine;
    buildParameters.BuildDirectory = buildDirectory;
    BuildProgressForm frmBuildProgress = new BuildProgressForm(buildParameters, teamFoundationServer);

    Wednesday, February 21, 2007

    TFSBuildManager UI Change (Tabbed View)

    It been a while since my last post. Anyway, I have published a new release of TFSBuildManager under CodePlex. The main and only change for this release is that the UI now supports control of multiple build types simultaneously by using tabs. Hope you would like this change. You can download the new version here. I would appreciate your comments on this change and about the application.

    Wednesday, January 31, 2007

    TFSBuildManager New Version

    I have released a new version of TFSBuildManager. You can download it here. I made some changes to the edit build type form and added some advanced properties that are inherited from the imported Microsoft.TeamFoundation.Build.targets file. There are some other cool features like "Execute Without Get" which actually resumes a build from the compilation point disabling the process of creating a workspace. This feature is very handy when you setup a new build machine and the build fails because of errors regarding the machine configuration and not because of source files. For the full feature list see the release change log.

    Sunday, January 28, 2007

    Export Data to Excel Sheet

    I have notice that there is a lot of traffic to my Blog because of a post I have about exporting Excel chart to an image. I thought that it would be good to share more stuff about Excel automation in C#. Below you can find a method to export data into excel sheet. This function uses a list view as the data source.

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Windows.Forms;
    using System.Globalization;
    using System.Threading;
    using System.Drawing;
    using ExcelAutomation = Microsoft.Office.Interop.Excel;

    namespace ExcelUtils
    public static class Excel
    private static void BorderAroundCell(ExcelAutomation.Range CellRange)



    public static void ReportFromListView(string reportName, ListView

    ExcelAutomation.Application excelApp = new ExcelAutomation.ApplicationClass();
    excelApp.UserControl = true;
    CultureInfo oldCultureInfo = Thread.CurrentThread.CurrentCulture;
    Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
    ExcelAutomation.Workbook workbook = excelApp.Workbooks.Add(Type.Missing);
    ExcelAutomation.Worksheet worksheet = (ExcelAutomation.Worksheet)workbook.Worksheets.get_Item(1);
    worksheet.Name = reportName;
    foreach (ColumnHeader columnHeader in listView.Columns)
    worksheet.Cells[1, columnHeader.Index + 1] = columnHeader.Text;
    string[] letters = new string[26]{"A", "B", "C", "D", "E", "F", "G", "H",
    "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
    "W", "X", "Y", "Z"};
    for (int i = 0; i < listView.Columns.Count; i++)

    string headerCell = letters.GetValue(i) + "1";
    worksheet.get_Range(headerCell, headerCell).Font.Bold = true;
    BorderAroundCell(worksheet.get_Range(headerCell, headerCell));
    worksheet.get_Range(headerCell, headerCell).Interior.ColorIndex = 36;
    for (int i = 0; i < listView.Items.Count; i++)

    for (int j = 0; j < listView.Columns.Count; j++)
    string dataCell = letters.GetValue(j) + (i + 2).ToString();
    worksheet.Cells[i + 2, j + 1] = listView.Items[i].SubItems[j].Text;
    BorderAroundCell(worksheet.get_Range(dataCell, dataCell));
    worksheet.Columns.HorizontalAlignment = ExcelAutomation.XlHAlign.xlHAlignLeft;
    excelApp.Visible = true;
    Thread.CurrentThread.CurrentCulture = oldCultureInfo;

    Monday, January 22, 2007

    New Terminals Version (Support for RDP 6.0)

    We have published a new Terminals version (1.0 Prodcution). You can download it at here.

    Here are the available changes for this release:

    1. Support for RDP 6:

    • 32bit color support.
    • Supports screen resolutions of up to 4096x2048.
    • Supports disabling clipboard redirection.
    • Enable smart card redirection.
    • Enable plug&play devices redirection.

    2. Save position and size.

    3. Nicer about box...

    4. Execute before connect (per connection and for all connections).

    5. Some additional bugs were fixed.


    Wednesday, January 17, 2007

    Company Dashboard

    We have installed a 42'' LCD Screen in our company headquarters. This LCD screen will be used for a dashboard displaying stats on our development process. Currently I'm using Excel reports created with TfsWarehouse OLAP cube (I have written about it before and I will post a guide in the future). The Excel reports are processed by a utility I wrote that extracts the charts from the Excel files to images in a directory that is displayed in a web site (I used javascript fade effect for it).

    Here are some pictures of the LCD screen:

    Monday, January 15, 2007

    5 Things That Will Make You Move To Vista

    I've started using Windows Vista on my desktop. I like it, it's working smooth and it looks good.
    I don't think that moving to Vista is essential but I've decided to work with it and find out what will make me consider moving all of my machines to Vista.
    So here are the first 5 features that made me smile:
    1. Start --> Run is dead. Start --> Start Search is the answer to those who won't leave their keyboards. Press the Windows button and start typing for searching programs and files. I did not open the programs group since I've installed Vista. It became useless.
    2. F2. This one made me smile the most. When you press F2 to rename a file the selected text is only the file name without the extension (for those of you that show file extensions). I wonder how long it took to develop this feature?
    3. Search is now part of the Explorer address bar. Just start typing and it show you the results in the same window. Performance is affected by indexing status.
    4. Burn button (Windows Explorer toolbar): Although I like using dedicated programs for CD/DVD burning I found the Burn button very useful. Select files and folders and press the Burn button to burn them.
    5. Restore previous versions (Folder, file context menu): If you will enable in system security Shadow Copies or System Restore you can get previous version of a file, folder. Good backup solution.

    To be continued.

    Wednesday, January 10, 2007


    I wrote a utility to manage build types called TFSBuildManager. You can download it's first release here. It is hosted under CodePlex.
    Main features of this utility are:
    • Start, stop a build
    • Change build/s quality
    • Delete, backup build/s
    • Edit build type

    I wrote it because I needed the ability to manage build types outside Visual Studio environment. Also, I needed some features that are not available through Visual Studio IDE.

    I'm planning to add:

    • Advanced build log
    • Add new Build Type
    • Build list filtering
    • Edit advanced Build Type properties


    Monday, January 08, 2007

    Export Excel Chart To Image

    I'm working on a dashboard that will display TFS reports. I thought using "SQL Server Business Intelligence Development Studio" for creating reports but found it not so stable. Anyway, I think that using TFS Excel integration for creating reports is the best way (I will write about how to do it in a future post). Now I have some excel reports but I want them to be displayed in our dashboard automatically (soon will be displayed on a 42'' LCD...). The solution for this was to export the excel chart from the report to an image that will be displayed in the dashboard site.
    Here's the code to export the image:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Configuration;
    using Excel = Microsoft.Office.Interop.Excel;
    using System.Globalization;
    using System.Threading;
    using System.IO;

    private static void ExportExcelChartToImage(string excelFile, string outputFile)

    //Object to send in com methods instead of null
    object missing = System.Reflection.Missing.Value;
    //Create a new excel application
    Excel.Application excelApplication = new Excel.ApplicationClass();
    //Saving the old culture info
    CultureInfo oldCultureInfo = Thread.CurrentThread.CurrentCulture;
    //Setting new culture info is en-us is not default (Disable exception)
    Thread.CurrentThread.CurrentCulture = new CultureInfo("en-us");
    //Open the excel document
    Excel.Workbook excelWorkbook = excelApplication.Workbooks.Open(excelFile,
    missing, missing, missing, missing, missing, missing, missing, missing,
    missing, missing, missing, missing, missing, missing);
    //Refresh the data from TFS
    //Taking into consideration that there's only one sheet
    Excel.Worksheet activeSheet = (Excel.Worksheet)excelWorkbook.ActiveSheet;
    //Again, there's only one chart on the sheet
    Excel.ChartObjects chartObjects = (Excel.ChartObjects)activeSheet.ChartObjects(missing);
    Excel.ChartObject chartObject = (Excel.ChartObject)chartObjects.Item(1);
    Excel.Chart chart = chartObject.Chart;
    //Set the filter (bmp, jpg...)
    string extension = Path.GetExtension(outputFile).Replace(".", "");
    //Export the image
    chart.Export(outputFile, extension, missing);
    //Save and close the workbook
    excelWorkbook.Close(false, excelFile, missing);
    //Set the old culture info
    Thread.CurrentThread.CurrentCulture = oldCultureInfo;
    //Close and free the excel application
    excelApplication = null;

    Tuesday, January 02, 2007

    Get List of Builds for Deleted Build Types

    To get a list of builds you can use:

    BuildData[] GetListOfBuilds(string teamProject, string buildType)

    How to get build types list I have mentions in: How to Get Build Types List.
    If you deleted a build type and you want to get list of builds from this type then you need to call GetListOfBuilds with String.Empty as the buildType parameter. This will return a full list of builds for the teamProject.

    public BuildData[] GetAllBuilds(string server, string project)
    TeamFoundationServer tfs = new TeamFoundationServer(server, CredentialCache.DefaultCredentials);
    BuildStore bs = (BuildStore)tfs.GetService(typeof(BuildStore));
    return bs.GetListOfBuilds(project, String.Empty);