Team Foundation Version Control client API example (RTM version)


[Update 3/10/2012] If you are using TFS 2010 or newer, there is an updated version control client API example.

[Update 6/13/06] While the documentation is not what it needs to be, you can find reference-style documentation on a significant amount of the API in the VS SDK (current release is April): http://blogs.msdn.com/buckh/archive/2005/12/09/502179.aspx.

I’ve updated this sample a few times before.  This is a really simple example that uses the version control API.  It shows how to create a workspace, pend changes, check in those changes, and hook up some important event listeners.  This sample doesn’t do anything useful, but it should get you going.

You have to supply a Team Project as an argument.  Note that it deletes everything under the specified Team Project, so don’t use this on a Team Project or server you care about.

The only real difference in this version is that it uses the TeamFoundationServer constructor (in beta 3, you were forced to use the factory class).

You’ll need to reference the following dlls to compile this example.

System.dll
Microsoft.TeamFoundation.VersionControl.Client.dll
Microsoft.TeamFoundation.Client.dll

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;

namespace BasicSccExample
{
    class Example
    {
        static void Main(string[] args)
        {
            // Verify that we have the arguments we require.
            if (args.Length < 2)
            {
                String appName = Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName);
                Console.Error.WriteLine(“Usage: {0} tfsServerName tfsTeamProjectPath”, appName);
                Console.Error.WriteLine(“Example: {0} http://tfsserver:8080 $/MyProject”, appName);
                Environment.Exit(1);
            }

            // Get a reference to our Team Foundation Server.
            String tfsName = args[0];
            TeamFoundationServer tfs = new TeamFoundationServer(tfsName);

            // Get a reference to Version Control.
            VersionControlServer versionControl = (VersionControlServer) tfs.GetService(typeof(VersionControlServer));

            // Listen for the Source Control events.
            versionControl.NonFatalError += Example.OnNonFatalError;
            versionControl.Getting += Example.OnGetting;
            versionControl.BeforeCheckinPendingChange += Example.OnBeforeCheckinPendingChange;
            versionControl.NewPendingChange += Example.OnNewPendingChange;

            // Create a workspace.
            Workspace workspace = versionControl.CreateWorkspace(“BasicSccExample”, versionControl.AuthenticatedUser);

            try
            {
                // Create a mapping using the Team Project supplied on the command line.
                workspace.Map(args[1], @”c:tempBasicSccExample”);

                // Get the files from the repository.
                workspace.Get();

                // Create a file.
                String topDir = Path.Combine(workspace.Folders[0].LocalItem, “sub”);
                Directory.CreateDirectory(topDir);
                String fileName = Path.Combine(topDir, “basic.cs”);
                using (StreamWriter sw = new StreamWriter(fileName))
                {
                    sw.WriteLine(“revision 1 of basic.cs”);
                }

                // Now add everything.
                workspace.PendAdd(topDir, true);

                // Show our pending changes.
                PendingChange[] pendingChanges = workspace.GetPendingChanges();
                Console.WriteLine(“Your current pending changes:”);
                foreach (PendingChange pendingChange in pendingChanges)
                {
                    Console.WriteLine(”  path: “ + pendingChange.LocalItem +
                                      “, change: “ + PendingChange.GetLocalizedStringForChangeType(pendingChange.ChangeType));
                }

                // Checkin the items we added.
                int changesetNumber = workspace.CheckIn(pendingChanges, “Sample changes”);
                Console.WriteLine(“Checked in changeset “ + changesetNumber);

                // Checkout and modify the file.
                workspace.PendEdit(fileName);
                using (StreamWriter sw = new StreamWriter(fileName))
                {
                    sw.WriteLine(“revision 2 of basic.cs”);
                }

                // Get the pending change and check in the new revision.
                pendingChanges = workspace.GetPendingChanges();
                changesetNumber = workspace.CheckIn(pendingChanges, “Modified basic.cs”);
                Console.WriteLine(“Checked in changeset “ + changesetNumber);
            }
            finally
            {
                // Delete all of the items under the test project.
                workspace.PendDelete(args[1], RecursionType.Full);
                PendingChange[] pendingChanges = workspace.GetPendingChanges();
                if (pendingChanges.Length > 0)
                {
                    workspace.CheckIn(pendingChanges, “Clean up!”);
                }

                // Delete the workspace.
                workspace.Delete();
            }
        }

        internal static void OnNonFatalError(Object sender, ExceptionEventArgs e)
        {
            if (e.Exception != null)
            {
                Console.Error.WriteLine(“Non-fatal exception: “ + e.Exception.Message);
            }
            else
            {
                Console.Error.WriteLine(“Non-fatal failure: “ + e.Failure.Message);
            }
        }

        internal static void OnGetting(Object sender, GettingEventArgs e)
        {
            Console.WriteLine(“Getting: “ + e.TargetLocalItem + “, status: “ + e.Status);
        }

        internal static void OnBeforeCheckinPendingChange(Object sender, ProcessingChangeEventArgs e)
        {
            Console.WriteLine(“Checking in “ + e.PendingChange.LocalItem);
        }

        internal static void OnNewPendingChange(Object sender, PendingChangeEventArgs e)
        {
            Console.WriteLine(“Pending “ + PendingChange.GetLocalizedStringForChangeType(e.PendingChange.ChangeType) +
                              ” on “ + e.PendingChange.LocalItem);
        }
    }
}

Comments (25)

  1. Buck Hodges says:

    Here’s a really simple example that uses the Beta 3 version control API.

  2. Buck Hodges says:

    Someone asked how to get the login dialog if the user fails to authenticate.&amp;nbsp; The code to do that…

  3. Rob Caron Blog Roundup:

    Organizing Team Projects

    Team System Wins Jolt Award

    Upgrading To Team Foundation…

  4. Ravi Terala says:

    Please use the TeamFoundationServer constructor _only_ if you need more than one TFS object to the same server with different credentials. Use TeamFoundationServerFactory otherwise.

  5. Buck Hodges says:

    Recently someone asked how to check in changes for another user.&amp;nbsp; There are at least two good scenarios…

  6. Buck Hodges says:

    Recently the question of how to compare files and folders came up.&amp;nbsp;&amp;nbsp;TFS version 1 doesn’t have&amp;nbsp;the…

  7. Buck Hodges says:

    I wrote this snippet recently to compare the edited files in a shelveset with an arbitrary checked-in…

  8. Martin gives us some excellent advice on what to avoid and what to do to make our Team Foundation Server life eaier!

  9. Buck Hodges says:

    I recently had to put together a list of links to code samples.&amp;nbsp; This isn’t even close to comprehensive,…

  10. Buck Hodges says:

    Rob Caron mentioned that the SDK documentation is now on the MSDN web site.&amp;nbsp; That SDK documentation…

  11. joshuaanthony says:

    I am looking at the steps necessary to move projects between two Team Foundation Servers where both…

  12. Got this cool list of code samples from Buck Hodges blog Version Control How to Write a Team Foundation

  13. Sucharith Vanguri says:

    Can someone please provide a code example on how to use the Workspace.CheckIn when there is a policy to be overridden. All examples I found so far just have the simple method call with the PendingChanges() and Comment as parameters.

    Thanks in advance.

    Regards

    Sucharith Vanguri

  14. buckh says:

    Sucharith, you can use the following overload.

    http://msdn.microsoft.com/en-us/library/bb139041.aspx

    The checkin notes and work item parameters may be null if you don’t have anything you want to specify there.

    To specify policy override information, you’ll need something like the following.  You can pass in null for policyFailures, or you can pass in the results you get from EvaluateCheckin().

    policyOverride = new PolicyOverrideInfo(overrideComment, policyFailures);

    Buck

  15. sufi says:

    hi.. i want to learn that. how am i check out only one file from tfs, after edit it and after checkin programmability…..

    is there any solution or code sample…

    thanks..

  16. Sridevi says:

    I am trying to get latest of a TFS folder programattically inside a asp.net web application. Get latest works fine if the web application runs under the Visual Studio Development Server, but if the web application runs as an IIS virtual directory, only the sub folders under the project are created, but I am not able to see the files under this folder after getting latest from tfs. Please help!!!

  17. buckh says:

    Sridevi, that sounds like a permissions problem for the account running under IIS.  Verify that it is able to create the files, as the file downloads are handled on a background thread.

    Buck

  18. Russellw says:

    Buck,

    I am trying to facilitate some auto-merging from one branch to another using the APIs.

    Nothing very complicated.

    However, my calls never return any changes, but I know there is one that I specifically made to test this.

    The same params from TF.exe does find the changed file…APIs do not.

    What am I missing?

    Dim TFSColl As TfsTeamProjectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(New Uri("http://SERVER:8080/Tfs/CollectionName&quot;))

    Dim vc As VersionControlServer = DirectCast(TFSColl.GetService(GetType(VersionControlServer)), VersionControlServer)

    'This path is to an existing workspace

    Dim wsinfo As WorkspaceInfo = Workstation.Current.GetLocalWorkspaceInfo("D:TFSMergeDemoMAIN")

    Dim myws As Workspace = wsinfo.GetWorkspace(TFSColl)

    Dim status As VersionControl.Client.GetStatus

    status = myws.Merge("$/RMT/Demo_DEV/Demo_DEV1", "$/RMT/SCMDemo_MAIN", VersionSpec.Latest, VersionSpec.Latest, LockLevel.None, RecursionType.Full, MergeOptions.None)

    'FAILS HERE…cuz here is no changes….however there should be.

    myws.CheckIn(myws.GetPendingChanges(), "Test123 Comment")

    ERROR: "The array must contain at least one element.

    Parameter name: checkinParameters.PendingChanges"

    This is driving me out of my mind…its seems very simple. Help?

  19. buckh says:

    Russell, sorry for the late reply.  You have set both version from and version to to VersionSpec.Latest, which is telling it to merge the changes in the latest changeset.  That's a cherry-pick merge, and it's not what you are after here.  What you want instead is to specify null for the version from, which will tell it to start from the beginning and pick up any changes that are not already in the target branch.

    msdn.microsoft.com/…/bb139332(v=VS.100).aspx

    Buck

  20. I like this post and it may fulfil my requirement. My requirement is to create a text file when users are checking in files in TFS so OnBeforeCheckinPendingChange can help me. I am new in TFS so can you please advice how do I use this above code to integrate with my existing TFS so that when OnBeforeCheckinPendingChange fires I can write code in this to create text file and add files in the text file.

    Please help me because my team is depending upon my input.

    Thanks in advance

  21. buckh says:

    Raj, the best approach may be to use the TfsTeamProjectCollectionFactory msdn.microsoft.com/…/microsoft.teamfoundation.client.tfsteamprojectcollectionfactory.aspx (replacement for TeamFoundationServerFactory) class to get the TFS reference inside of Team Explorer or Visual Studio.  Then you can hook into that event for checkins in the GUI.  The post blogs.msdn.com/…/factory-vs-constructor.aspx talks about what the factory does.

    Buck

  22. Thanks for reply Buck. Sorry I am new in TFS and I didn't understand your reply 100%. I didn't understand "(replacement for TeamFoundationServerFactory) class to get the TFS reference inside of Team Explorer or Visual Studio.  Then you can hook into that event for checkins in the GUI." this statement inside double quotes. Specially "get the TFS reference inside of Team Explorer or Visual Studio" and "hook into that event for checkins in the GUI".

    So let me tell you what I need. My requirement is to create a text file when user checks in to TFS. So OnBeforeCheckinPendingChange is the event I can use. So If I create a class library of the above code can you please advice where should I copy my DLL so that when ever a user checks in a file in TFS my event OnBeforeCheckinPendingChange fires and my code inside that creates a text file. I have already created the dll but can't find any post for deploying it.

    Sorry for bothering you but if you can please help me it would very kind of you.

    Regards

    Raj

  23. Hi Buck,

    Sorry again but I am still waiting for your help. I had to postpone our implementation because I could not come up with a solution. Can you please help me I sent you a post on  Wed, Jul 6 2011.

  24. Here's a sample which also includes where to find the DLLs which may not appear in the Add Reference dialog: msdn.microsoft.com/…/bb286958.aspx

    "You can find them at %ProgramFiles%Microsoft Visual Studio 10.0Common7IDEReferenceAssembliesv2.0."

  25. Erçağ says:

    Hi,

    I’m trying to check-in but return 0.

    Why return zero?