Buck Hodges

Visual Studio Online, Team Foundation Server, MSDN

May, 2006

Posts
  • Buck Hodges

    Compare the content changes in a shelveset with any checked-in version

    • 3 Comments

    I wrote this snippet recently to compare the edited files in a shelveset with an arbitrary checked-in version of the same files.  It's another example of how to use the API to show differences.  See How to compare (diff) trees at different versions using the API for a different example of comparing checked-in files.

    If you are just getting started with the version control API, you'll want to start with the basic example.

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

    namespace DiffShelveset
    {
        class Program
        {
            static void Main(string[] args)
            {
                if (args.Length != 2)
                {
                    Console.Error.WriteLine("This command shows the differences between the shelved edits");
                    Console.Error.WriteLine("and the specified version of the same files.");
                    Console.Error.WriteLine("  Usage: diffshelveset shelvset[;shelvesetOwner] versionSpec");
                    Console.Error.WriteLine("  Example: diffshelveset BugFix;Alice C123");
                    Environment.Exit(1);
                }

                // Determine the server by using the local workspace cache.
                WorkspaceInfo wsInfo = Workstation.Current.GetLocalWorkspaceInfo(Environment.CurrentDirectory);
                if (wsInfo == null)
                {
                    Console.Error.WriteLine("The current directory is not part of a workspace.");
                    Environment.Exit(1);
                }

                TeamFoundationServer tfs = new TeamFoundationServer(wsInfo.ServerUri.AbsoluteUri);
                VersionControlServer versionControl = (VersionControlServer) tfs.GetService(typeof(VersionControlServer));

                try
                {
                    DiffShelvedChanges(versionControl, args[0], args[1]);
                }
                catch (VersionControlException e)
                {
                    Console.Error.WriteLine(e.Message);
                    Environment.Exit(1);
                }
            }

            static void DiffShelvedChanges(VersionControlServer versionControl,
                                           String shevlesetArg, String versionArg)
            {
                // A TeamFoundationServer object is always the "parent" of a VersionControlServer
                // object.
                TeamFoundationServer tfs = versionControl.TeamFoundationServer;

                // The shelvesetName;shelvesetOwner format is exactly the same as
                // workspaceName;workspaceOwner, so the same class is used for parsing both.
                String shelvesetName, shelvesetOwner;
                WorkspaceSpec.Parse(shevlesetArg, RepositoryConstants.AuthenticatedUser,
                                    out shelvesetName, out shelvesetOwner);

                // To improve performance, the PendingChange objects do not normally contain the URLs for
                // downloading the file content.  In this case, we know that we are going to be downloading
                // the file contents, so we set the last parameter to true.  Since we want all changes in
                // the shelveset, we specify null for the ItemSpecs.
                PendingSet[] pendingSets = versionControl.QueryShelvedChanges(shelvesetName, shelvesetOwner,
                                                                              nulltrue);
                if (pendingSets.Length == 0)
                {
                    Console.Error.WriteLine("No shelveset matched.");
                    Environment.Exit(1);
                }
                else if (pendingSets.Length > 1)
                {
                    Console.Error.WriteLine("More than one shelveset matched.");
                    Environment.Exit(1);
                }

                PendingChange[] shelvedChanges = pendingSets[0].PendingChanges;
                if (shelvedChanges.Length == 0)
                {
                    Console.Error.WriteLine("You don't have permission to any of the files involved.");
                    Environment.Exit(1);
                }

                // Convert the string argument into a ChangesetVersionSpec, LabelVersionSpec, DateVersionSpec,
                // or WorkspaceVersionSpec (all derive from the abstract VersionSpec class).
                VersionSpec versionSpec = VersionSpec.ParseSingleSpec(versionArg,
                                                                      RepositoryConstants.AuthenticatedUser);

                // Now we can diff each change against the version specified.
                foreach (PendingChange shelvedChange in shelvedChanges)
                {
                    // We only want files that are being edited, but there's nothing to diff if 
                    // the file is guaranteed not to exist at a different version.
                    if (shelvedChange.ItemType != ItemType.File ||
                        !shelvedChange.IsEdit || shelvedChange.IsAdd || shelvedChange.IsBranch)
                    {
                        continue;
                    }

                    DiffItemShelvedChange diffChange = new DiffItemShelvedChange(shelvesetName,
                                                                                 shelvedChange);

                    // We could have directly created a DiffItemVersionedFile, however it wouldn't
                    // take into account the fact that the file may have had a different name.
                    // The CreateTargetDiffItem() will take care of all the arcane details, whereas
                    // the constructor assumes you are specifying exactly what you want.
                    IDiffItem diffVersion = Difference.CreateTargetDiffItem(versionControl,
                                                                            shelvedChange,
                                                                            versionSpec);

                    // Since the VisualDiff*() methods do not block, we call the more specific
                    // method so that we can have the call block until the external tool exits.
                    // If you want to see an example of producing textual diff output instead,
                    // see the diff call in
                    // http://blogs.msdn.com/buckh/archive/2006/04/06/project_diff.aspx.
                    DiffOptions diffOpts = new DiffOptions();
                    diffOpts.UseThirdPartyTool = true;
                    Difference.DiffFiles(versionControl, diffVersion, diffChange, diffOpts,
                                         String.Empty, true);
                }
            }
        }
    }
  • Buck Hodges

    Editing documents anywhere using Outlook free documents

    • 3 Comments

    About a month ago, I wrote about using Outlook with RPC over HTTP.  I recently stumbled across an old blog post by Jeremy Kelly called Using your Mailbox to Store Work-in-Progress documents.  He mentions a feature called "free docs."  Combining this with Outlook over HTTP is really very useful.  Here's how it works.

    1. Create a Word document, write something, and save it.
    2. Go to Windows Explorer and drag and drop the Word file into one of your folders in Outlook.
    3. Double click on the file in Outlook, modify it, and save it.
    4. Go to another machine running Outlook over HTTP.  You can double click the file and edit it some more (notice that your changes from step 3 are there).

    What's so cool about that?  It's a secure way to be able to work on your documents wherever you have Outlook over HTTP (office desktop, laptop elsewhere), the file is updated in place, automatically synchronized (no more searching for the latest version), and backed up for free on the Exchange server.  By secure I mean that the documents are stored on the corporate exchange server, the communications with the Exchange server over the Internet are encrypted, and the documents only exist on machines under my control.

    That's a lot more convenient than a thumb drive or emailing document attachments to yourself.

    The part I'd like to be able to do is to combine steps 1 and 2 by being able to directly create the document in the Outlook folder without having to go through the intermediate step of creating a file to be dragged into Outlook.  If anyone out there knows how to do that, please let me know.

  • Buck Hodges

    Using TFS with Web Application Projects

    • 1 Comments

    There's a helpful FAQ posted in the ASP.NET forums regarding using Team Foundation Server with the newly released Web Application Projects for Visual Studio.

    Issue 6 - Using TFS Team Build

    Issue 6 - Using TFS Team Build
    The May 2006 release of Web Application Projects supports building with Team Build on a Team Foundation Server (TFS). However, you will need to manually add the "Microsoft.WebApplication.targets" file to your Team Foundation Server for it to work.

    1. On the computer running Team Build, navigate to the "C:\Program Files\MSBuild\Microsoft\VisualStudio\v8.0" directory.
    2. In this directory create a "WebApplications" directory.
    3. Place the "Microsoft.WebApplication.targets" file in the "WebApplications" directory. This file can be found at the same location on your developer system that has been updated with the May 2006 release of Web Application Projects.

    After performing these steps Team Build should be able to successfully build a web-project build with the new Web Application Project type.

    Additionally, if you have an older version of a Web Application Project, you will need to add the WebApplication.targets line (shown in blue and bold) after the normal CSharp.targets or VBasic.targets line in your .csproj or .vbproj file (all new or newly migrated projects will have this line automatically).

    <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
    <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v8.0\WebApplications\Microsoft.WebApplication.targets" />

    Issue 7 - Using TFS Source Control

    Issue 7 - Using TFS Source Control
    There is a known issue with the enterprise source control system in the Team Foundation Server (TFS) which incorrectly identifies codebehind classes for .aspx. and .ascx files as folders.

    To workaround, do not use "File/Source Control/Open from Source Control". Instead, manually get the solution using Team Explorer and open the solution from local disk.

    This problem will be fixed in a future release of Team Foundation Server.

  • Buck Hodges

    Quick guide to backing up your TFS databases

    • 0 Comments

    Jeff Atwood at Verigo Software has posted a nice visual guide to backing up your TFS data (based on the official MSDN TFS backup documentation).

    A Visual Guide to Backing Up a Team Foundation Server database

    He promises to provide a guide to restoring the data as well.

Page 1 of 1 (4 items)