Editing my original answer: You are asking "WHY does the pipeline not let you pipe from one ForEach to another ForEach," as opposed to a practical solution. This requires a basic definition of what the pipeline does. From
- PowerShell: Automating Administrative Tasks by Michael Shepard; Chendrayan Venkatesan; Sherif Talaat; Brenton J.W. Blawat
"The pipeline in PowerShell is a mechanism to get data from one command to another. Simply put, the data that is output from the first command is treated as input to the next command in the pipeline. "
The pipeline in PowerShell passes .NET framework objects as opposed to other types of shells which may pass text. So, based off the definition above, what are you expecting the For-EachObject to output to be the input from pipeline for the next sequence? When you're doing a Where-Object or Select-Object, you're refining the collection. You've already stated that the objects are sent to Write-Host. There would not be anything in the pipeline as an output after the ForEach finishes.
I'm not sure the advantage to the daisy chain of pipelining. I could be wrong about this, I generally break sequences with variables. The ForEach will consume and operate on every single item of the collection piped in, and then produce or pipe out what exactly, to the next in the piping chain? I understand ForEach can accept pipeline input as a collection of objects, such as an array. So I see advantages to its use of only iterating through the number of items, as opposed to the classic
for($i = 0; $i-lt $collectionOfOjbects.Length; $i++)
{
Verb-Noun $collectionOfObjects[$i]
}
Is it possible to try the selecting/sorting refining first, then pipe that to the ForEach iterations?
$myFirst20MailboxStatsInkorg = $mailboxstatistics | Select-Object -First 20 | Where { $_.FolderPath.Contains("/Inkorg") -eq $True }
#first round of iteration:
$myFirst20MailboxStatsInkorg | ForEach-Object -Begin{
Write-Host "Begin"
} -Process{
#Write-Host "Process"
Write-Host $($_.FolderPath)
} -End{
Write-Host "End"
}
#second round of iteration
$myFirst20MailboxStatsInkorg | ForEach-Object{
Write-Host "test"
}
Write-Hostis notWrite-Output. You're generally off using neither (explicitly), just return the value in the pipeline itself (which has the same effect as aWrite-Outputcall).Write-Hostisn't blocking anything -- it just isn't part of the pipeline at all. Your secondForEachdoesn't do anything because no objects are passed to it. If you want to print the value and pass it in the pipeline, useWrite-Hostin addition to producing pipeline output (but the final result will end up at the console anyway, so this may result in confusing output).Tee-Objectto copy to a variable or file in addition to the pipeline (it can't copy directly to the host output, though).