TFS 服务器 API 仅列出 XAML 生成定义
Posted
技术标签:
【中文标题】TFS 服务器 API 仅列出 XAML 生成定义【英文标题】:TFS server API only list the XAML build definitions 【发布时间】:2017-01-09 14:28:55 【问题描述】:我正在尝试从 TFS2015 构建定义中获取信息。我们有大约 100 个 XAML 格式的构建定义和大约 50 个新的 2015 格式。 该服务器是内部 Team Foundation Server。 (Microsoft Visual Studio 团队基础服务器 版本 15.105.25910.0)
我没有使用其他 API,而是使用此处推荐的 Microsoft.TeamFoundationServer.ExtendedClient:https://blogs.msdn.microsoft.com/buckh/2015/08/10/nuget-packages-for-tfs-and-visual-studio-online-net-client-object-model/。
这是我的代码示例:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;
using Serilog;
namespace TFSExperiment
class Program
// see https://blogs.msdn.microsoft.com/buckh/2015/08/10/nuget-packages-for-tfs-and-visual-studio-online-net-client-object-model/
//Needs nuget package Install-Package Microsoft.TeamFoundationServer.ExtendedClient -Version 14.102.0
// to use serilogg: Install-Package Serilog ; Install-Package Serilog.Sinks.RollingFile
static void Main(string[] args)
var myLog = new LoggerConfiguration()
.WriteTo.RollingFile("..\\..\\Applog\\mylog-Date.log").CreateLogger();
TfsConfigurationServer configurationServer =
TfsConfigurationServerFactory.GetConfigurationServer(new Uri("https://tfs.inhouseserver2015.org/tfs/"));
ReadOnlyCollection<CatalogNode> collectionNodes =
configurationServer.CatalogNode.QueryChildren(new[] CatalogResourceTypes.ProjectCollection, false,
CatalogQueryOptions.None);
CatalogNode defultTfsCol = collectionNodes.AsQueryable().Single(c=>c.Resource.DisplayName.Equals("DefaultCollection"));
Console.WriteLine(defultTfsCol.Resource.DisplayName);
TfsTeamProjectCollection tfsProjectCollection =
configurationServer.GetTeamProjectCollection(new Guid(defultTfsCol.Resource.Properties["InstanceId"]));
tfsProjectCollection.Authenticate();
var buildServer = (IBuildServer)tfsProjectCollection.GetService(typeof(IBuildServer));
ReadOnlyCollection<CatalogNode> projectNodes = defultTfsCol.QueryChildren(
new[] CatalogResourceTypes.TeamProject ,
false, CatalogQueryOptions.None);
foreach (var proj in projectNodes)
var buildDefinitionList = new List<IBuildDefinition>(buildServer.QueryBuildDefinitions(proj.Resource.DisplayName));
foreach (var buildDef in buildDefinitionList)
Console.WriteLine(buildDef.Name);
myLog.Information($"buildDef.Id --buildDef.Name --buildDef.BuildServer.BuildServerVersion ");
Console.WriteLine(" Hit any key to exit ");
Console.ReadKey();
【问题讨论】:
【参考方案1】:正如 Eddie - MSFT 和 Tore Østergaard 的回答,我不得不使用其余的 api。但看起来我还必须使用旧的 api 从 builddefinitions 中获取所有信息。从 restapi 我得到了构建的名称,但没有得到 xaml 构建的深度信息。
我想从指出 Octopus Deploy 项目名称的变量中收集信息。我在这里发布代码以防有人遇到类似问题。
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Build.WebApi;
using Microsoft.TeamFoundation.Common;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;
using Newtonsoft.Json;
using Serilog;
using Serilog.Core;
namespace ListOctopusProjectsAndTfsBuilds
class Program
// see https://blogs.msdn.microsoft.com/buckh/2015/08/10/nuget-packages-for-tfs-and-visual-studio-online-net-client-object-model/
//Needs nuget package Install-Package Microsoft.TeamFoundationServer.ExtendedClient -Version 14.102.0
// to use serilogg: Install-Package Serilog ; Install-Package Serilog.Sinks.RollingFile
static Logger _myLog = new LoggerConfiguration()
.WriteTo.RollingFile($"..\\..\\Applog\\myBuildDeflog-DateTime.Now:yyyyMMddHHHHmmss.log").CreateLogger();
static void Main(string[] args)
Console.WriteLine("Start looking for BuildDefs");
Dictionary<string, string> octopusDeployDictionary = GetvNextBuildDefVariable( new Uri("https://inhouseserver2015/tfs/DefaultCollection"), "YourTfsProject", "OctoProj");
Dictionary<string, string> octopusDeployXamlDictionary = GetXamlBuildDefVariable(new Uri("https://inhouseserver2015/tfs/DefaultCollection"), "YourTfsProject", "ArgOctopusProjectsToPublish");
Console.WriteLine("Builds vnext defs -- Octopus project");
foreach (var cd in octopusDeployDictionary)
Console.WriteLine($"cd.Key; cd.Value");
Console.WriteLine("Builds xaml defs -- Octopus project");
foreach (var cd in octopusDeployXamlDictionary)
Console.WriteLine($"cd.Key; cd.Value");
Console.ReadLine();
private static Dictionary<string, string> GetXamlBuildDefVariable(Uri tfsUri, string tfsProject, string buildDefVar)
var collection = tfsUri.LocalPath.Split('/')[2];
//Define Reg expression ahead so it can faster parse xml and find the Octopus Deploy projectname.
Regex findArgOctopusProjectsToPublish = null;
try
findArgOctopusProjectsToPublish = new Regex($"x:Key=\"buildDefVar\".*<x:String>([^<]*)",
RegexOptions.IgnoreCase | RegexOptions.Singleline);
catch (ArgumentException ex)
_myLog.Error(ex, "Error with RegularExpression syntax");
Dictionary<string, string> tfsVarBuildDefDict = new Dictionary<string, string>();
TfsConfigurationServer configurationServer =
TfsConfigurationServerFactory.GetConfigurationServer(tfsUri));
ReadOnlyCollection<CatalogNode> collectionNodes =
configurationServer.CatalogNode.QueryChildren(new[] CatalogResourceTypes.ProjectCollection, false,
CatalogQueryOptions.None);
CatalogNode defultTfsCol =
collectionNodes.AsQueryable().Single(c => c.Resource.DisplayName.Equals(collection));
TfsTeamProjectCollection tfsProjectCollection =
configurationServer.GetTeamProjectCollection(new Guid(defultTfsCol.Resource.Properties["InstanceId"]));
tfsProjectCollection.Authenticate();
var buildServer = (IBuildServer) tfsProjectCollection.GetService(typeof(IBuildServer));
ReadOnlyCollection<CatalogNode> projectNodes = defultTfsCol.QueryChildren(
new[] CatalogResourceTypes.TeamProject,
false, CatalogQueryOptions.None);
var buildDefinitionList =
new List<IBuildDefinition>(buildServer.QueryBuildDefinitions(tfsProject));
foreach (var buildDef in buildDefinitionList)
Debug.Assert(findArgOctopusProjectsToPublish != null, "findArgOctopusProjectsToPublish != null");
var octopusProjectsToPublish =
findArgOctopusProjectsToPublish?.Match(buildDef.ProcessParameters).Groups[1].Value;
if (octopusProjectsToPublish.IsNullOrEmpty())
octopusProjectsToPublish = "NoOctopus Projekt";
tfsVarBuildDefDict.Add(buildDef.Name, octopusProjectsToPublish);
_myLog.Information($"buildDef.Id --buildDef.Name --buildDef.BuildServer.BuildServerVersion ");
return tfsVarBuildDefDict;
private static Dictionary<string, string> GetvNextBuildDefVariable(Uri tfsUri,string tfsProject,string buildDefVar)
Dictionary<string, string> tfsVarBuildDefDict = new Dictionary<string, string>();
TfsTeamProjectCollection ttpc =
new TfsTeamProjectCollection(tfsUri);
BuildHttpClient bhc = ttpc.GetClient<BuildHttpClient>();
var definitions = bhc.GetDefinitionsAsync(project: tfsProject);
var client = new WebClient UseDefaultCredentials = true;
foreach (var buildDef in definitions.Result)
if (buildDef.Type == DefinitionType.Build)
var json = client.DownloadString(buildDef.Url);
BuildDefinition result = JsonConvert.DeserializeObject<BuildDefinition>(json);
if (result.Variables.ContainsKey(buildDefVar))
tfsVarBuildDefDict.Add(buildDef.Name, result.Variables[buildDefVar].Value.ToString());
_myLog.Information($"buildDef.Name Octoproject: result.Variables[buildDefVar].Value.ToString()");
else
_myLog.Information($"buildDef.Name BuildType buildDef.Type ");
return tfsVarBuildDefDict;
【讨论】:
【参考方案2】:您正在使用只能获取 XAML 构建的旧版 soap API。
假设您已安装最新的 .NET Client Libraries,您可以使用库中的 Rest API 来获取 XAML 和 vNext 构建,如下所示:
using System;
using System.Collections.Generic;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Build.WebApi;
namespace ConsoleApplication1
class Program
static void Main(string[] args)
Uri tfsurl = new Uri("http://xxxx:8080/tfs/CollectionName");
TfsTeamProjectCollection ttpc = new TfsTeamProjectCollection(tfsurl);
BuildHttpClient bhc = ttpc.GetClient<BuildHttpClient>();
List<Build> builds = bhc.GetBuildsAsync("ProjectName").Result;
foreach (Build bu in builds)
Console.WriteLine(bu.BuildNumber);
Console.ReadLine();
【讨论】:
您好,谢谢。我需要关于 xaml 构建时没有得到的变量的构建定义信息。我不得不使用booth api:s。【参考方案3】:Microsoft.TeamFoundationServer.ExtendedClient 中的 API 主要用于提供与 XAML 构建的向后兼容性。据我所知,他们不支持 Build vNext,因为它们是在他们的时代之前编写的。
正如您提供的链接所建议的那样,REST API 是未来的遵循方式。
【讨论】:
好吧,也许我读得太快了,我读到了有关 Microsoft.TeamFoundationServer.ExtendedClient 的信息:“..因为目前 TFS 2015 或 VSO 中并非每个 API 都可以作为 REST API 使用,所以会有一些案例你必须在哪里使用这个包......”所以我认为一切都在这个里面。 (因此名称扩展“ 我尝试了Rest API,但没有让Windows身份验证工作我只有System.Net.Http.HttpRequestException:响应状态代码不表示成功:401(未授权)。 你试过设置 UseDefaultCredentials = true;在您的 WebClient 对象上?以上是关于TFS 服务器 API 仅列出 XAML 生成定义的主要内容,如果未能解决你的问题,请参考以下文章
为啥用于获取 TFVC 变更集的 TFS Rest API 仅返回 256 个项目?