我在PowerShell中使用TFS PowerTools Cmdlet尝试从我的服务器获取有关Changeset和相关WorkItem的一些信息。我已将问题归结为我不理解的行为,我希望它不是TFS特定的(所以有人可能会向我解释这个问题:))
这是我可以开始工作的唯一命令:
Get-TfsItemHistory C:\myDir -recurse -stopafter 5 | % { Write-Host $_.WorkItems[0]["Title"] }
它做了我所期望的 - Get-TfsItemHistory返回一个包含5个ChangeSet的列表,并将它们传递给foreach,它打印出第一个关联WorkItem的Title。那我的问题是什么?我正在尝试编写一个大型脚本,我更喜欢将事物编写为更像C#程序(powershell语法让我哭泣)。每当我尝试以任何其他方式编写上述内容时,WorkItems集合都为空。
以下命令(我认为在逻辑上等效)不起作用(WorkItems集合为空):
$items = Get-TfsItemHistory C:\myDir -recurse -stopafter 5 $items | ForEach-Object { Write-Host $_.WorkItems[0]["Title"] }
我真的更喜欢的那个:
$items = Get-TfsItemHistory C:\myDir -recurse -stopafter 5 foreach ($item in $items) { $item.WorkItems[0]["Title"] # do lots of other stuff }
我读了一篇关于'foreach'运算符和ForEach-Object Cmdlet之间差异的文章,但这似乎更像是一场性能争论。这似乎是关于何时使用管道的问题。
我不确定为什么所有这三种方法都不起作用。任何见解都表示赞赏。
答案 0 :(得分:11)
这确实令人困惑。现在,解决方法就是抓住这样的项目:
$items = @(Get-TfsItemHistory . -r -Stopafter 25 |
Foreach {$_.WorkItems.Count > $null; $_})
这会访问WorkItems集合,这似乎会导致填充此属性(我知道 - WTF?)。在我想使用foreach关键字的情况下,我倾向于使用@()
生成数组。使用foreach关键字的事情是它将迭代包含$ null的标量值。因此,如果查询没有返回任何内容,$items
将被赋予$ null,并且foreach将循环一次,并将$item
设置为null。现在PowerShell通常非常好地处理空值。但是,如果将该值交还给.NET Framework,通常不会那么宽容。 @()
将保证数组中包含0,1或N个元素。如果它为0,那么foreach循环将根本不执行它的主体。
BTW你最后的方法 - foreach ($item in $items) { ... }
- 应该可以正常工作。