Blog Entries Tagged: tee

Team Explorer Everywhere on Windows Azure

September 16, 2011 9:03 PM

Brian Harry recently announced our preview of Team Foundation Server hosted on Windows Azure. I'm happy to add that the Team Explorer Everywhere team has developed a preview of our cross-platform client for the hosted TFS Service preview.

When you sign up for the hosted TFS Service, you'll be able to download the Team Explorer Everywhere client. Check out Brian's blog for a special invitation code.

Introducing the TFS SDK for Java

June 6, 2011 9:47 PM

We recently introduced the TFS SDK for Java, to allow Java developers to target applications to Team Foundation Server. One of the great features of an SDK for Java is that it allows cross-platform access to TFS.

As you might know, I'm the resident Mac guy on the TFS team, so I wanted to whip up a little demo for how you might use this on Mac OS. This little sample shows how to pop up a Growl notification every time a new work item is created that falls within a specific query. Obviously it's fairly simplistic, but hopefully it's a good starting point for thinking about what you might be able to do with the new SDK.

import java.util.HashSet;
import java.util.Set;

import com.microsoft.tfs.core.TFSTeamProjectCollection;
import com.microsoft.tfs.core.clients.workitem.WorkItem;
import com.microsoft.tfs.core.clients.workitem.WorkItemClient;
import com.microsoft.tfs.core.clients.workitem.query.WorkItemCollection;
import com.microsoft.tfs.core.profiles.Profile;
import com.microsoft.tfs.core.profiles.ProfileProperties;

public class WitToast
{
    /*
      * This is a simple WIQL query to execute - work items included
      * in this query will be notified for.
      */
    public static final String WIQL = "select [System.Id], [Microsoft.VSTS.Common.StackRank], [Microsoft.VSTS.Common.Priority], [System.WorkItemType], [System.State], [System.Title] from WorkItems where [System.AssignedTo] = @me and [System.State] <> 'Closed' and [System.WorkItemType] <> 'Shared Steps' order by [Microsoft.VSTS.Common.StackRank], [Microsoft.VSTS.Common.Priority], [System.WorkItemType], [System.Id]";

    public static void main(String[] args) throws Exception {
        Growl growl = new Growl("Team Foundation Server");
        growl.setImageFile("/tmp/tee.icns");

        Set workItems = new HashSet();

        /* Build a connection profile */
        Profile profile = new Profile();
        profile.addValue(ProfileProperties.SERVER_URL,
            "http://tfs.contoso.com:8080/tfs/DefaultCollection");
        profile.addValue(ProfileProperties.USER_NAME, "username");
        profile.addValue(ProfileProperties.USER_DOMAIN, "DOMAIN");
        profile.addValue(ProfileProperties.PASSWORD, "Password");

        /* Get the work item SOAP service */
        WorkItemClient wit = new TFSTeamProjectCollection(profile)
            .getWorkItemClient();

        /*
         * Set up the initial set of work items - anything created
         * after this initial query will be notified for.
         */
        WorkItemCollection results = wit.query(WIQL);

        for (int i = 0; i < results.size(); i++) {
            workItems.add(results.getWorkItem(i));
        }

        while (true) {
            results = wit.query(WIQL);

            for (int i = 0; i < results.size(); i++) {
                WorkItem workItem = results.getWorkItem(i);

                /*
                 * This work item hasn't been seen - pop a notification.
                 */
                if (!workItems.contains(workItem)) {
                    growl.notify("The work item " + workItem.getTitle()
                        + " was created.");

                    workItems.add(workItem);
                }
            }

            Thread.sleep(10000);
        }
    }

    private static class Growl
    {
        private final String applicationName;

        public Growl(final String applicationName) {
            this.applicationName = applicationName;
        }

        public void notify(final String message) {
            final String[] growlArguments = new String[5];
            growlArguments[0] = "/usr/local/bin/growlnotify";
            growlArguments[1] = "-n";
            growlArguments[2] = applicationName;
            growlArguments[3] = "-m";
            growlArguments[4] = message;

            try
            {
                Runtime.getRuntime().exec(growlArguments);
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
}

Team Explorer Überall

April 8, 2011 5:01 PM

One of the interesting things about working for Microsoft instead of a tiny little startup company is that they actually expect us to do all the things that people expect out of a software company. For example: Microsoft actually ships localized software! Which means that if you're in Germany, you actually get dialogs and buttons and other widgets in German. I suppose this is something that those crazy Germans have come to expect, but it was quite a revelation to this programmer who grew up in the redneckier parts of Illinois and thinks that the French road signs in Canada are quite exotic[1].

When it was suggested[2] to us that we'd need to ship a localized version of Team Explorer Everywhere, I laughed. Several years of strings piling on top of each other and we're supposed to extract those and get them translated? Ouch.

Fortunately, when we were brought into Microsoft, our team was beefed up with some very smart people who don't laugh at hard problems. And so we present to you language packs available for download in German, French and Japanese.

  1. Hey, I'm down with kilometers, but arrêt?
  2. And by suggested, I mean told.

Team Explorer Everywhere 2010 SP1 (Beta)

November 5, 2010 1:23 PM

Yesterday we released the beta of the first service pack of Team Explorer Everywhere, and while a service pack is just supposed to be a roll-up of bugfixes, we managed to sneak in some great new features.

I mentioned before that Team Explorer Everywhere 2010 was sort of a tough release for us... fortunately we got a second chance with our service pack and we were able to add some new features that we didn't have time to include for the initial release.

We were able to add Gated Check-in, which is a great feature for bringing your continuous integration up a notch to ensure that your code quality stays high. This was one of the flagship features of TFS 2010 and something we use internally, so it was especially important for us to provide it to our customers.

We added support for conflict resolution using the built-in Eclipse Merge Tool. While we've always had the ability to use an external merge tool like SourceGear DiffMerge, we'd never investigated using the internal Eclipse compare/merge tool to resolve a conflict. In SP1, we're going to add that as the Eclipse merge tool as a resolution option so that you don't need to install a 3rd party tool.

Finally - and perhaps most visibly - we've added rich text editing for Work Items, which will allow you to easily edit the rich text in HTML field controls in work items. (Previously we provided a poorer experience with HTML in controls.) In SP1, we're able to leverage the web browsers on each platform to render a nice rich text editor.

Of course, we've also been busy fixing a bunch of bugs. We're really pleased with the way our first service pack has come together, and we think that this is a release that you'll be very happy with.

Team Explorer Everywhere 2010

April 29, 2010 12:25 AM

We've finally announced the release of Team Explorer Everywhere 2010[1] and now that we're finally done, I can say without any hesitance that this is the proudest I've ever been to have shipped a product. Yes, we've added a lot of new features, but I'm much more proud of the huge increase in quality... that almost didn't happen.

Right after the Teamprise 3.0 release, we stepped back and took a hard look at the codebase for our UI products. We'd done the typical startup engineering effort way back in the 1.0 days: basically, quick and dirty, and we cut some corners. Some of the code between Teamprise Explorer and our plug-in for Eclipse was duplicated, in order to adapt between Eclipse IResources and the model objects we used in Teamprise Explorer. This was a pretty thin layer of duplication, but whenever there was a bug there, we had to remember to fix it in both places. More annoying, however, was that some of the more advanced controls - like the Pending Changes View - were written back before we all had a firm grasp on the SWT toolkit and as we added more functionality, those controls became increasingly problematic. The worst, however, was our very brittle contact points with Eclipse. The Eclipse IDE lets you perform very advanced, and very powerful, refactoring operations that we couldn't always convert to the representative TFS pending changes.

We realized after 3.0 that we simply couldn't keep moving forward with our UI code base in the shape that it was. We decided to undertake a rewriting of our entire connection experience, all the places we interacted with Eclipse, all of the shared code between Teamprise Explorer and the Plug-in for Eclipse and many of the advanced controls like the Pending Changes View. This was a pretty bold undertaking - the history of software engineering is littered with examples of why you shouldn't do the "big rewrite". But we were convinced that we could make some very important changes in our framework[2] and still leverage a lot of our old code. That is, do a big rewrite without doing a "big rewrite", and launch this new version around the same time Microsoft shipped their next version of TFS.

Of course, what we didn't take into account was that Microsoft would acquire us halfway through our development cycle and we'd suddenly have to peel off from development to do a lot of due diligence, then move halfway across the country and integrate into a whole new company in the middle of our big rewrite. So in the middle of November, when we all flew to North Carolina for the first time to meet the rest of the team and get them up to speed on our software, we had a very awkward meeting.

"Well," I said, standing in front of a whiteboard drawing out our architecture. "This is more or less how it's supposed to work. The good news is that it's a pretty good architecture... I think. The bad news is that it's not done... and it's not at all proven."

So we talked about the big rewrite a little bit longer and then we had a tough decision to make. Do we keep going down the road of the rewrite, with a hard ship date staring us in the face? Or do we throw it away and go back to the old Teamprise 3.0 codebase and just fix what we can and add some new features?

After a lot of debate, we decided to keep going with the big rewrite, with (scarily aggressive) milestones to make sure that we were making the right decision and could still back out if we needed to.

Fortunately, we didn't need to. Thanks to some herculean efforts on the part of the entire team, we completely rearchitected our clients for Team Explorer Everywhere 2010... and thanks to some excellent testing, we've been held to a much higher standard, too. This is - without question - the highest quality release of our plug-in for Eclipse that we've ever done, and we couldn't be prouder.

  1. Formerly "Eaglestone". Surprisingly - even Wikipedia knows about our little project.
  2. Mostly creating a framework.
Edward Thomson is a Software Engineer at Microsoft. He uses a Mac. He writes primarily in Java. He likes cognitive dissonance.