更新:我对此做了一个公共扩展。
更新:这适用于 Azure DevOps 2019。
在 TFS 2018u1 中,以下工作:
Import-Module "Microsoft.TeamFoundation.DistributedTask.Task.Common"
Import-Module "Microsoft.TeamFoundation.DistributedTask.Task.Internal"
Add-Type -Assembly "Microsoft.TeamFoundation.DistributedTask.WebApi"
$VSS = Get-VssConnection -TaskContext $distributedTaskContext
$AgentCli = $VSS.GetClient([Microsoft.TeamFoundation.DistributedTask.WebApi.TaskAgentHttpClient])
$AgentConfig = Get-Content "$Env:AGENT_HOMEDIRECTORY\.agent" -Raw | ConvertFrom-Json
$Agent = $AgentCli.GetAgentAsync($AgentConfig.PoolId, $Env:AGENT_ID, $TRUE, $FALSE, $NULL, $NULL, [System.Threading.CancellationToken]::None).GetAwaiter().GetResult()
if($Agent.UserCapabilities.MyCapability)
{
Write-Host "Got the capability!";
}
以默认参数结尾的长字符串CancellationToken::None
是为了与 Powershell 4 兼容。PS4 不支持值类型方法参数的默认值,PS5 支持。
这个片段做了一些非常有问题的事情——它依赖于代理配置文件的位置和结构。这是脆弱的。问题是该GetAgentAsync
方法需要池 ID 和代理 ID,并且前者没有暴露在环境变量中。一种稍微不那么骇人听闻的方法是检查所有池并通过代理 ID 找到正确的池:
$Pools = $AgentCli.GetAgentPoolsAsync($NULL, $NULL, $NULL, $NULL, $NULL, [System.Threading.CancellationToken]::None).GetAwaiter().GetResult()
$Demands = New-Object 'System.Collections.Generic.List[string]'
foreach($Pool in $Pools)
{
$Agent = $AgentCli.GetAgentsAsync($Pool.ID, $Env:AGENT_NAME, $TRUE, $FALSE, $NULL, $Demands, $NULL, [System.Threading.CancellationToken]::None).Result
if($Agent -and $Agent.Id -eq $Env:AGENT_ID)
{
Break
}
}
这依赖于另一个未记录的实现细节,特别是代理 ID 是全球唯一的。这似乎一直持续到 TFS 2018,但谁知道呢。
当您使用 时$distributedTaskContext
,任务是使用人工用户身份“项目集合构建服务”(而不是代理服务帐户)连接回 TFS。每个集合中都有一个这样的用户,他们是不同的。为了允许在集合中的版本中运行的任务向代理查询用户功能,您需要将 Reader 角色授予相关池(或所有池)到名为“项目集合构建服务 ( TheCollectionName ) 的用户帐户)" 来自该集合。
看起来某些操作还将池上的隐式读者角色授予任务标识。
或者,您可以VssConnection
使用 Windows 凭据从头开始构建,并授予代理帐户对池的读取者角色。