简体   繁体   中英

Visual Studio 2015 build drop location

Our company recently updated TFS to 2015 update 1. After that context menu item named Drop folder disappeared from completed builds. I found nothing about it and how to bring it back. When I click Open on completed build, VS opens web version of TFS where I forced to click through the menus and copy drop folder path manually. So I decided to write a simple extension that will add this item to the menu.
Some googling brought me to this page . But it seems that the example code is quite old and not working in VS2015:

IVsTeamFoundationBuild vsTfBuild = (IVsTeamFoundationBuild)GetService(typeof(IVsTeamFoundationBuild));
IBuildDetail[] builds = vsTfBuild.BuildExplorer.CompletedView.SelectedBuilds;

Property SelectedBuilds is always empty. I suppose that it relates to old window from VS2010. It returns items that are instance of IBuildDetail interface.
So I found this piece of code here :

var teamExplorer = (ITeamExplorer)ServiceProvider.GetService(typeof(ITeamExplorer));
var page = teamExplorer.CurrentPage;
var buildsPageExt = (IBuildsPageExt)page.GetExtensibilityService(typeof(IBuildsPageExt));
var build = buildsPageExt.SelectedBuilds[0];

Here build is the instance of IBuildModel interface. It lacks DropLocation property.

Is there any way to found drop location of selected build? Or maybe latest build?

You can use IBuildDedetail.DropLocation in .NET client libraries for Visual Studio Team Services (and TFS) . Basic code for your reference:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Client;

namespace BuildAPI
{
    class Program
    {
        static void Main(string[] args)
        {
            string project = "http://xxx.xxx.xxx.xxx";
            TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(new Uri(project));
            IBuildServer ibs = tpc.GetService<IBuildServer>();
            var builds = ibs.QueryBuilds("TeamProjectName");
            foreach (IBuildDetail ibd in builds)
            {
                Console.WriteLine(ibd.DropLocation);
                Console.ReadLine();
            }
        }
    }
}

So, after digging through TFS API, I ended up with this workaround.

    private void MenuItemCallback(object sender, EventArgs e)
    {
        var context = (ITeamFoundationContextManager)ServiceProvider.GetService(typeof(ITeamFoundationContextManager));
        IBuildServer buildServer = context.CurrentContext.TeamProjectCollection.GetService<IBuildServer>();
        var teamExplorer = (ITeamExplorer)ServiceProvider.GetService(typeof(ITeamExplorer));
        var buildsPageExt = (IBuildsPageExt)teamExplorer.CurrentPage.GetExtensibilityService(typeof(IBuildsPageExt));
        var menuCommand = (MenuCommand)sender;

        if (menuCommand.CommandID.Guid == CommandSetCompleted)
        {
            foreach (var buildDetail in buildsPageExt.SelectedBuilds)
                Process.Start("explorer.exe", GetBuild(buildServer, buildDetail).DropLocation);
        }

        if (menuCommand.CommandID.Guid == CommandSetFavorite)
        {
            var definitions = buildsPageExt.SelectedFavoriteDefinitions.Concat(buildsPageExt.SelectedXamlDefinitions).ToArray();

            foreach (var build in GetLatestSuccessfulBuild(buildServer, definitions))
                Process.Start("explorer.exe", build.DropLocation);
        }
    }

    private IBuildDetail GetBuild(IBuildServer buildServer, IBuildModel buildModel)
    {
        Uri buildUri = new Uri(buildModel.GetType().GetProperty("UriToOpen").GetValue(buildModel).ToString());
        return buildServer.GetBuild(buildUri);
    }

    private IBuildDetail[] GetLatestSuccessfulBuild(IBuildServer buildServer, IDefinitionModel[] buildDefinitions)
    {
        var spec = buildServer.CreateBuildDetailSpec(buildDefinitions.Select(bd => bd.Uri));
        spec.MaxBuildsPerDefinition = 1;
        spec.QueryOrder = BuildQueryOrder.FinishTimeDescending;
        spec.Status = BuildStatus.Succeeded;

        var builds = buildServer.QueryBuilds(spec);

        return builds.Builds;
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM