Let's say you have a collection of objects, and you wish to perform the same action over each object in that collection.
Seems like a ForEach job, right? Let's use this as an starting point:
$myArray = @('Here', 'are', 'some', 'things')
$myArray | ForEach-Object `
-Begin { $i = 0 } `
-Process { $i++ } `
-End { Write-Host $i }
In this example, we go through each object, increment i, and finally output the value of $i to the console.
4
Not particularly helpful, but it is going over each element at least. In a real-world scenario however, we probably want to do something with each value in the collection.
We can grab the value of the object using $_ :
$myArray = @('Here', 'are', 'some', 'things')
$myArray | ForEach-Object `
-Begin { Write-Host "Start!" } `
-Process { Write-Host $_ } ` -End {Write-Host "Finished!"}
Start!
Here
are
some
things
Finished!
Rewriting as a function
What if we wanted to do something a bit more involved than writing everything out to the screen?
We could create a function, and run it inside the Process section, passing in the parameter. Or, we could create a function that iterates through the collection itself.
Let's consider the above example, writing it as a function:
$myArray = @('Here', 'are', 'some', 'things')
function DoStuff
{
Begin { Write-Host "Start!" }
Process { Write-Host $_ }
End { Write-Host "Finished!" }
}
# Run DoStuff on every element in myArray
$myArray | DoStuff
Here, we've taken the -Begin, -Process and -End arguments, and placed them inside the function. This allows us to pipe the $myArray variable simply with the function name:
$myArray | DoStuff
Start!
Here
are
some
things
Finished!
Of course, in this example we didn't even need the Begin and End steps. These can be omitted:
$myArray = @('Here', 'are', 'some', 'things')
function DoStuff
{
Process {
# Assume this is a long, complex method
Write-Host $_
}
}
$myArray | DoStuff
Here
are
some
things
Writing functions like this makes it much easier to iterate over them, whilst keeping the code readable.
Iterating over objects
In these examples, the object is simply a string.
If the object has properties, then we can get the property from $_:
function DoStuff
{
# Get the Name from the object only Process { Write-Host $_.Name } }
$objectA = [PSCustomObject]@{ Name = 'Here' }
$objectB = [PSCustomObject]@{ Name = 'are' }
$objectC = [PSCustomObject]@{ Name = 'some' }
$objectD = [PSCustomObject]@{ Name = 'things' }
$myArray = @($objectA, $objectB, $objectC, $objectD)
$myArray | DoStuff