PowerShell Error ForEach / Piping

I use the TFS PowerTools cmdlets in PowerShell to try to get some information about the servers and their associated WorkItems from my server. I digested the problem before a behavior that I don't understand, and I hope this is not a specific TFS (so someone can explain this problem to me :))

Here is the only command I can work with:

 Get-TfsItemHistory C: \ myDir -recurse -stopafter 5 |  % {Write-Host $ _. WorkItems [0] ["Title"]}

It does what I expect - Get-TfsItemHistory returns a list of 5 ChangeSets, and it passes them to foreach, which displays the header of the first associated WorkItem. So what is my problem? I am trying to write a large script, and I prefer to code things to look more like a C # program (powershell syntax makes me cry). Whenever I try to do the above in any other way, the collection of WorkItems is null.

The following commands (which I interpret as logically equivalent) do not work (the WorkItems collection is null):

 $ items = Get-TfsItemHistory C: \ myDir -recurse -stopafter 5
 $ items |  ForEach-Object {Write-Host $ _. WorkItems [0] ["Title"]}

One that I would prefer:

 $ items = Get-TfsItemHistory C: \ myDir -recurse -stopafter 5
 foreach ($ item in $ items)
 {
     $ item.WorkItems [0] ["Title"]
     # do lots of other stuff
 }

I read an article about the difference between the foreach statement and the ForEach-Object cmdlet, but this seems to be more related to the performance discussion. This seems to be a problem about when the pipeline is used.

I'm not sure why all three of these approaches do not work. Any insight appreciated.

+7
foreach powershell piping tfs2010
source share
1 answer

This is really confusing. At the moment, a detour is a capture of the following elements:

$items = @(Get-TfsItemHistory . -r -Stopafter 25 | Foreach {$_.WorkItems.Count > $null; $_}) 

Gets access to the WorkItems collection, which seems to make this property populate (I know - WTF?). I use @() to create an array in cases where I want to use the foreach keyword. The thing with the foreach keyword is that it will iterate over the scalar value, including $ null. That way, if the query returns nothing, $items gets $ null, and foreach will iterate over the loop once with $item set to null. Now PowerShell as a whole deals with zeros very well. However, if you pass this value back to the .NET Framework, this is usually not so forgiving. @() guarantees an array containing either 0, 1, or N elements in it. If it is 0, then the foreach loop will not execute its body at all.

By the way, your last approach - foreach ($item in $items) { ... } - should work fine.

+8
source share

All Articles