Geeks With Blogs

News




View Tarun Arora's profile on LinkedIn

profile for Tarun Arora at Stack Overflow, Q&A for professional and enthusiast programmers

Tarun Arora - Visual Studio ALM MVP ALM, Agile, Automation, Performance Testing, Software QA, Cloud, ...

Great! You have reached that point where you would like to extend TFS. The first step is to connect to TFS programmatically.

Download: 

Working Demo - VS 2010

Working Demo - VS 2012

In this blog post I’ll be showing you,

  • How to connect to TFS programmatically using TFS 2010 SDK
  • How to connect to TFS programmatically using TFS 2012 SDK
  • DLL references required to connect to TFS programmatically
  • Connectivity classes & scope
  • How to establish a connection interactively
  • How to establish a connection without user intervention

How to connect to TFS programmatically using TFS 2010 SDK

  1. Visual Studio Extension Gallery: Download VS 2010 SDK from extension gallery http://visualstudiogallery.msdn.microsoft.com/25622469-19d8-4959-8e5c-4025d1c9183d?SRC=VSIDE

    image

  2. Extension Manager: Alternatively you can also download this from the visual studio extension manager

    image

How to connect to TFS programmatically using TFS 2012 SDK

  1. Visual Studio Extension Gallery: Download VS 2012 SDK from gallery http://visualstudiogallery.msdn.microsoft.com/b2fa5b3b-25eb-4a2f-80fd-59224778ea98

    image_thumb[7]

  2. Extension Manager: Alternatively you can also download this from the visual studio extension manager

    image_thumb[1]

    DLL references required to connect to TFS programmatically

    Create a new Windows Forms Application project and add reference to TFS Common and client DLLs.

    Note - If Microsoft.TeamFoundation.Client and Microsoft.TeamFoundation.Common do not appear on the .NET tab of the References dialog box, use the Browse tab to add the assemblies.

    You can find them at %ProgramFiles%\Microsoft Visual Studio 10.0\Common7\IDE\ReferenceAssemblies\v2.0.

    OR %ProgramFiles%\Microsoft Visual Studio 11.0\Common7\IDE\ReferenceAssemblies\v2.0.

    Required References

    using Microsoft.TeamFoundation.Client;
    using Microsoft.TeamFoundation.Framework.Client;
    using Microsoft.TeamFoundation.Framework.Common;

    image_thumb[4]

    Connectivity classes & scope

    There are several ways to connect to TFS, the two classes of interest are,

    Option 1 Class – TfsTeamProjectCollection

    Microsoft.TeamFoundation.Client
    {
        public class TfsTeamProjectCollection : TfsConnection
        {
            public TfsTeamProjectCollection(RegisteredProjectCollection projectCollection);
            public TfsTeamProjectCollection(Uri uri);
            public TfsTeamProjectCollection(RegisteredProjectCollection projectCollection, IdentityDescriptor identityToImpersonate);
            public TfsTeamProjectCollection(Uri uri, ICredentials credentials);
            public TfsTeamProjectCollection(Uri uri, ICredentialsProvider credentialsProvider);
            public TfsTeamProjectCollection(Uri uri, IdentityDescriptor identityToImpersonate);
            public TfsTeamProjectCollection(RegisteredProjectCollection projectCollection, ICredentials credentials, ICredentialsProvider credentialsProvider);
            public TfsTeamProjectCollection(Uri uri, ICredentials credentials, ICredentialsProvider credentialsProvider);
            public TfsTeamProjectCollection(RegisteredProjectCollection projectCollection, ICredentials credentials, 
                                                              ICredentialsProvider credentialsProvider, IdentityDescriptor identityToImpersonate);
            public TfsTeamProjectCollection(Uri uri, ICredentials credentials, ICredentialsProvider credentialsProvider, IdentityDescriptor identityToImpersonate);
    
            public override CatalogNode CatalogNode { get; }
            public TfsConfigurationServer ConfigurationServer { get; internal set; }
            public override string Name { get; }
    
            public static Uri GetFullyQualifiedUriForName(string name);
            protected override object GetServiceInstance(Type serviceType, object serviceInstance);
            protected override object InitializeTeamFoundationObject(string fullName, object instance);
        }
    } 

    Option 2 Class – TfsConfigurationServer

    namespace Microsoft.TeamFoundation.Client
    {
        public class TfsConfigurationServer : TfsConnection
        {
            public TfsConfigurationServer(RegisteredConfigurationServer application);
            public TfsConfigurationServer(Uri uri);
            public TfsConfigurationServer(RegisteredConfigurationServer application, IdentityDescriptor identityToImpersonate);
            public TfsConfigurationServer(Uri uri, ICredentials credentials);
            public TfsConfigurationServer(Uri uri, ICredentialsProvider credentialsProvider);
            public TfsConfigurationServer(Uri uri, IdentityDescriptor identityToImpersonate);
            public TfsConfigurationServer(RegisteredConfigurationServer application, ICredentials credentials, ICredentialsProvider credentialsProvider);
            public TfsConfigurationServer(Uri uri, ICredentials credentials, ICredentialsProvider credentialsProvider);
            public TfsConfigurationServer(RegisteredConfigurationServer application, ICredentials credentials, 
                                                                             ICredentialsProvider credentialsProvider, IdentityDescriptor identityToImpersonate);
            public TfsConfigurationServer(Uri uri, ICredentials credentials, ICredentialsProvider credentialsProvider, IdentityDescriptor identityToImpersonate);
    
            public override CatalogNode CatalogNode { get; }
            public override string Name { get; }
    
            protected override object GetServiceInstance(Type serviceType, object serviceInstance);
            public TfsTeamProjectCollection GetTeamProjectCollection(Guid collectionId);
            protected override object InitializeTeamFoundationObject(string fullName, object instance);
        }
    }

    Difference between TfsConfigurationServer and TfsTeamProjectCollection

    When you use the TfsConfigurationServer class, you access the services for the whole server. When you use the TfsTeamProjectCollection class, you access the services for the team project collection. For example, the ITeamFoundationRegistry service for TfsConfigurationServer provides registered properties of the server. The same service that is acquired from TfsTeamProjectCollection provides the registered properties of a team project collection. Some services apply to team project collections only.

    Service

    TfsConfigurationServer (Server Level)

    TfsTeamProjectCollection (collection-level)

    ITeamFoundationRegistry Yes Yes
    IIdentityManagementService Yes Yes
    ITeamFoundationJobService Yes Yes
    IPropertyService Yes Yes
    IEventService Yes Yes
    ISecurityService Yes Yes
    ILocationService Yes Yes
    TswaClientHyperlinkService Yes Yes
    ITeamProjectCollectionService Yes
    IAdministrationService Yes Yes
    ICatalogService Yes
    VersionControlServer Yes
    WorkItemStore Yes
    IBuildServer Yes
    ITestManagementService Yes
    ILinking Yes
    ICommonStructureService3 Yes
    IServerStatusService Yes
    IProcessTemplates Yes

    Note – The TeamFoundationServer class is obsolete. Use the TfsTeamProjectCollection or TfsConfigurationServer classes to talk to a 2010 & 2012 Team Foundation Server. In order to talk to a 2005 or 2008 Team Foundation Server use the TfsTeamProjectCollection class.

    How to establish a connection interactively

    Use the Team Project Picker class if you want to allow the user to choose what collection or project they want to connect to…

    // Variables I want to use globally
    private static TfsTeamProjectCollection _tfs;
    private static ProjectInfo _selectedTeamProject;
    
    // Connect to TFS Using Team Project Picker
    public static void ConnectToTfsUsingTeamProjectPicker()
    {
             // The  user is allowed to select only one project
             var tfsPp = new TeamProjectPicker(TeamProjectPickerMode.SingleProject, false);
    
             tfsPp.ShowDialog();
    
             // The TFS project collection
             _tfs = tfsPp.SelectedTeamProjectCollection;
    
             if (tfsPp.SelectedProjects.Any())
             {
                  //  The selected Team Project
                  _selectedTeamProject = tfsPp.SelectedProjects[0];
             }
     }

    The TeamProjectPicker is very powerful. As you can see below, you have the option to give restrictive options to the user.See this blog post here for more details on Team Project Picker.

    public class TeamProjectPicker : IDisposable
    {
            public TeamProjectPicker();
            // Don't allow the user to switch between team project collections
            public TeamProjectPicker(TeamProjectPickerMode mode, bool disableCollectionChange);
            // Load the picker by passing default credentials but giving the user the option to change credentials
            public TeamProjectPicker(TeamProjectPickerMode mode, bool disableCollectionChange, ICredentialsProvider credentialsProvider);
           // Change the accept button text to something else
            public string AcceptButtonText { get; set; }
            public string Text { get; set; }
            public TfsTeamProjectCollection HostActiveTeamProjectCollection { get; set; }
            // Pre select the team projects before loading the dialogue       
            public ProjectInfo[] SelectedProjects { get; set; }
            public TfsTeamProjectCollection SelectedTeamProjectCollection { get; set; }
            // Capture the AcceptButtonClick event
            public event CancelEventHandler AcceptButtonClick;
            public void Dispose();
            public void SetDefaultSelectionProvider(ITeamProjectPickerDefaultSelectionProvider provider);
            public DialogResult ShowDialog();
            public DialogResult ShowDialog(IWin32Window parentWindow);
    }

    How to establish a connection without user intervention

    You also have the option of establishing a connection to TFS un-interactively. In this case, you need to know the URI of the team project collection that you wish to connect to.

    So, the question is, how to figure out what the TFS Team Project Collection URI is. This can easily be found out by looking at the properties of the team project collection.

    How do i know what the URI of my TFS server is,

    image

    image

    OR

    image_thumb[15]

    image_thumb[19]

    Note – You need to be have Team Project Collection view details permission in order to connect, expect to receive an authorization failure message if you do not have sufficient permissions.

    Case 1: Connect by URI

    // URI of the team project collection
    string _myUri = @"https://tfs.codeplex.com:443/tfs/tfs30";
    
    TfsConfigurationServer configurationServer =
                    TfsConfigurationServerFactory.GetConfigurationServer(new Uri(_myUri));

    Case 2: Connect by URI, prompt for credentials

    // URI of the team project collection
    string _myUri = @"https://tfs.codeplex.com:443/tfs/tfs30";
    
    TfsConfigurationServer configurationServer =
        TfsConfigurationServerFactory.GetConfigurationServer(new Uri(_myUri), new UICredentialsProvider());
    configurationServer.EnsureAuthenticated();

    Case 3: Connect by URI, custom credentials

    In order to use this method of connectivity you need to implement the interface ICredentailsProvider 
    
        public class ConnectByImplementingCredentialsProvider : ICredentialsProvider
        {
            public ICredentials GetCredentials(Uri uri, ICredentials iCredentials)
            {
                return new NetworkCredential("UserName", "Password", "Domain");
            }
    
            public void NotifyCredentialsAuthenticated(Uri uri)
            {
                throw new ApplicationException("Unable to authenticate");
            }
        }
    
    And now consume the implementation of the interface
    
        // URI of the team project collection
         string _myUri = @"https://tfs.codeplex.com:443/tfs/tfs30";
    
        ConnectByImplementingCredentialsProvider connect = new ConnectByImplementingCredentialsProvider();
        ICredentials iCred = new NetworkCredential("UserName", "Password", "Domain");
        connect.GetCredentials(new Uri(_myUri), iCred);
                
        TfsConfigurationServer configurationServer =
                           TfsConfigurationServerFactory.GetConfigurationServer(new Uri(_myUri), connect);
        configurationServer.EnsureAuthenticated();

    Programmatically query TFS using the TFS SDK for all Team Project Collections and retrieve all Team Projects and output the display name and description of each team project.

    CatalogNode catalogNode = configurationServer.CatalogNode;
    
    ReadOnlyCollection<CatalogNode> tpcNodes = catalogNode.QueryChildren(
                    new Guid[] { CatalogResourceTypes.ProjectCollection },
                    false, CatalogQueryOptions.None);
    
    // tpc = Team Project Collection
    foreach (CatalogNode tpcNode in tpcNodes)
    {
          Guid tpcId = new Guid(tpcNode.Resource.Properties["InstanceId"]);
          TfsTeamProjectCollection tpc = configurationServer.GetTeamProjectCollection(tpcId);
    
          // Get catalog of tp = 'Team Projects' for the tpc = 'Team Project Collection'
          var tpNodes = tpcNode.QueryChildren(
                    new Guid[] { CatalogResourceTypes.TeamProject },
                    false, CatalogQueryOptions.None);
    
          foreach (var p in tpNodes)
          {
              Debug.Write(Environment.NewLine + " Team Project : " + p.Resource.DisplayName + " - " + p.Resource.Description + Environment.NewLine);
          }
    }

    Output

    image

    You can download a working demo that uses TFS SDK 2010 to programmatically connect to TFS 2010.

    Screen Shots of the attached demo application,

    image

    image

    Suggested Further Reading

    Please refer to other posts tagged under TFS API here http://geekswithblogs.net/TarunArora/category/12805.aspx

    Enjoy In love

    Posted on Saturday, June 18, 2011 5:05 PM TFS API | Back to top


    Comments on this post: TFS SDK: Connecting to TFS 2010 & TFS 2012 Programmatically

    # re: TFS 2010 SDK: Connecting to TFS 2010 Programmatically–Part 1
    Requesting Gravatar...
    Hi Sumit,

    This is a very good question. There are several ways to access the TFS notification alerts, you have already listed two of them. I'll tell u the third one for which you will not require to make any changes to the TFS server.

    Problem - In my enterprise the TFS server is really locked down and except for certain machine administrators not too many people have access to the server. I needed to hook up to the build notification alerts that are triggered by TFS every time a build is triggered, failed or completed.

    Solution - I created a windows service that is installed on a client machine (this service can pretty much be installed any where and just needs to be in the same network as your server but not necessarily the same machine). This service runs under the user identity of an individual that has admin access to the team project collection and read access to the team project i am interested to listen to the alerts for. The service subscribes to the url that tfs publishes the alerts to and is continuously polling this url for any new alerts. As soon as the service receives an alerts it start to execute the business logic i want to run against it. If you are interested to see this in action have a look at tfsdeployer.codeplex.com. The service code is also available for download.

    Feel free to touch base if you have further questions.

    HTH.
    Cheers, Tarun
    Left by Tarun Arora on Oct 16, 2011 6:42 PM

    # re: TFS 2010 SDK: Connecting to TFS 2010 Programmatically–Part 1
    Requesting Gravatar...
    Thanks for such an elaborate response, for now i have got TFS access and i am following this blog post for TFS events
    http://www.ewaldhofman.nl/post/2010/08/02/How-to-use-WCF-to-subscribe-to-the-TFS-2010-Event-Service-rolling-up-hours.aspx
    Left by Sumit on Oct 27, 2011 11:46 AM

    # re: TFS 2010 SDK: Connecting to TFS 2010 Programmatically–Part 1
    Requesting Gravatar...
    Can you please let me know how to Log defect in TFS using program
    Left by Kapil Sharma on Jan 15, 2012 3:15 PM

    # re: TFS 2010 SDK: Connecting to TFS 2010 Programmatically–Part 1
    Requesting Gravatar...
    Hi Kapil,

    Defects are work items, you want to create bug type work item programmatically. If that is correct, please refer to this link that shows you how to create work items using the TFS object model. http://msdn.microsoft.com/en-us/library/bb130322.aspx

    Cheers, Tarun
    Left by Tarun Arora on Jan 15, 2012 3:36 PM

    # re: TFS 2010 SDK: Connecting to TFS 2010 Programmatically–Part 1
    Requesting Gravatar...
    I am not able to connect to TFS2011 preview version using this sample. It fails on EnsureAuthentication method.

    I am using the code as below:

    ICredentials iCred = new NetworkCredential("windowsliveemail@live.com", "pwd", "Windows Live ID");

    Let me know how we connect to TFS 2011 (TFSPreview) using the sample above. Thanks.

    Left by Pranav on Feb 28, 2012 9:30 PM

    # re: TFS 2010 SDK: Connecting to TFS 2010 Programmatically–Part 1
    Requesting Gravatar...
    Simple, descriptive, useful (and even works :)). Thanks!!
    Left by Mario on Feb 29, 2012 3:19 PM

    # re: TFS 2010 SDK: Connecting to TFS 2010 Programmatically–Part 1
    Requesting Gravatar...
    Doesnt work for us... Getting an error:
    Message: Team Foundation services are not available from server http://XXXXXX (server uri) (for administrator):
    HTTP code 404: Not Found Inner Exception: System.Net.WebException: The remote server returned an error: (404) Not Found.
    at System.Net.HttpWebRequest.GetResponse()
    at Microsoft.TeamFoundation.Client.TeamFoundationClientProxyBase.AsyncWebRequest.Exec.Request(Object obj)


    I am running it on my machine, the uri is correct. I am in the project collection administrators group.
    Left by Corey on Mar 15, 2012 8:41 PM

    # re: TFS 2010 SDK: Connecting to TFS 2010 Programmatically–Part 1
    Requesting Gravatar...
    Hi Corey,

    Can you try the following code and see if you are able to connect?

    private TfsTeamProjectCollection _tfs;
    private string _selectedTeamProject;
    private IBuildServer _bs;
    private WorkItemStore _wis;

    // Connect to TFS and pick team project
    private void ConnectToTfsAndPickAProject()
    {
    TeamProjectPicker tfsPP = new TeamProjectPicker(TeamProjectPickerMode.SingleProject, false);
    tfsPP.ShowDialog();
    this._tfs = tfsPP.SelectedTeamProjectCollection;
    this._selectedTeamProject = tfsPP.SelectedProjects[0].Name;
    }

    Thanks
    Tarun
    Left by Tarun Arora on Mar 16, 2012 9:20 AM

    # re: TFS 2010 SDK: Connecting to TFS 2010 Programmatically–Part 1
    Requesting Gravatar...
    Hi Pranav,

    You will be able to connect to TFS Preview, simply do the following. Connect using the below code, this will in theory give you a pop up and allow you to specify the details and connect.

    private TfsTeamProjectCollection _tfs;
    private string _selectedTeamProject;
    private IBuildServer _bs;
    private WorkItemStore _wis;

    // Connect to TFS and pick team project
    private void ConnectToTfsAndPickAProject()
    {
    TeamProjectPicker tfsPP = new TeamProjectPicker(TeamProjectPickerMode.SingleProject, false);
    tfsPP.ShowDialog();
    this._tfs = tfsPP.SelectedTeamProjectCollection;
    this._selectedTeamProject = tfsPP.SelectedProjects[0].Name;
    }

    Once you are connected look at the identity of the user, that should be in the _tfs. <space> i.e. AuthorizedIdentity, Credentials. http://msdn.microsoft.com/en-us/library/ff732550.aspx

    Last i tried I had my domain as ClaimsIdentity, username as arora.tarun@hotmail.com. Please let me know if this works for you.

    Cheers, Tarun
    Left by Tarun Arora on Mar 16, 2012 9:25 AM

    # re: TFS 2010 SDK: Connecting to TFS 2010 Programmatically–Part 1
    Requesting Gravatar...
    I can't find the .dlls to reference. They're not on the .NET tab or in the folder you referenced above. I'm using VS 2010.
    Left by Laurie on Mar 19, 2012 7:17 PM

    # re: TFS 2010 SDK: Connecting to TFS 2010 Programmatically–Part 1
    Requesting Gravatar...
    The code you posted for Case 3, using custom credentials, will yield unexpected results.

    If you are running that code from a machine in the domain, and the user you are logged in as (or are running as) has the proper permissions in TFS, then it will work fine, but a problem arises if you are trying to connect to a TFS server from outside of the domain or say, across a vpn.

    Essentially, the credentials provider seems to be ignored, and regardless of the credentials that it returns, you will fail to authenticate.

    The easy solution is to not use the factory to get the TfsConfigurationServer, but to call one of the constructors of TfsConfigurationServer directly, ie;

    configurationServer = new Microsoft.TeamFoundation.Client.TfsConfigurationServer(new Uri(_myUri), iCred, connect);

    This call will use the credentials in iCred and allow you to properly authenticate.




    Left by Gary on May 03, 2012 2:40 PM

    # re: TFS 2010 SDK: Connecting to TFS 2010 Programmatically–Part 1
    Requesting Gravatar...
    Hi Tarun,

    This really helps but I just have one issue.

    Message: Team Foundation services are not available from server http://XXXXXX (server uri) (for administrator):
    HTTP code 404: Not Found Inner Exception: System.Net.WebException: The remote server returned an error: (404) Not Found.
    at System.Net.HttpWebRequest.GetResponse()
    at Microsoft.TeamFoundation.Client.TeamFoundationClientProxyBase.AsyncWebRequest.Exec.Request(Object obj)

    Please help!!

    Regards
    Dinesh
    Left by Dinesh Kumar Jain N on May 15, 2012 12:42 PM

    # re: TFS 2010 SDK: Connecting to TFS 2010 Programmatically–Part 1
    Requesting Gravatar...
    Hi Tarun,

    Your Post has really helped me to develop the Admin tool.

    I implemented code permissions for Groups at Version control level. But not able to find how to get permissions for Groups at Team project level.

    It would be great if you provide some guidance.

    Thanks & Regards,
    Nagaraj
    Left by Nagaraj on Jun 26, 2012 4:48 PM

    # re: TFS 2010 SDK: Connecting to TFS 2010 Programmatically–Part 1
    Requesting Gravatar...
    Hey, I need to search some files in TFS Programmatically, can you please help in this regards?

    Thanks Much!
    Left by Nir on Oct 01, 2012 3:11 PM

    # re: TFS SDK: Connecting to TFS 2010 & TFS 2012 Programmatically
    Requesting Gravatar...
    Is there any way to execute TFS query programatially. I am looking for a simple way.
    Left by Kailash on Dec 07, 2012 2:58 AM

    # re: TFS SDK: Connecting to TFS 2010 & TFS 2012 Programmatically
    Requesting Gravatar...
    Hi Tarun,

    How can i show the team Members in each Project(If i have many projects)?
    Left by Wajeeha on Jan 16, 2013 2:11 PM

    comments powered by Disqus

    Copyright © Tarun Arora [Microsoft MVP] | Powered by: GeeksWithBlogs.net | Join free