PowerShell Foreach-Object

PowerShell Foreach-Object Cmdlet

Looping is a core method for scripting.  About the only topic of confusion in PowerShell is that between the ForEach operator and the Foreach-Object cmdlet.

In a nutshell if you need pipelining study this page.  If you want a quick easy method study the simple PowerShell loops here.

My mission on this page is to give you simple examples on how to master the PowerShell ForEach pipeline loop.  As you become more proficient in PowerShell, so the instructions grow in complexity.

Topics for PowerShell’s Foreach-Object Cmdlet


PowerShell’s Foreach-Object Cmdlet

The Foreach-Object cmdlet specializes in controlling loops that accept pipeline input.  Another of this cmdlet’s interesting features is the -Begin and -End parameters.

Example 1: PowerShell Foreach-Object Cmdlet

The purpose of this script is to interrogate the Windows System event log, and then save the results to a file.

# PowerShell Foreach-Object
$LogPath = "C:\temp\system.txt"
$I = 0
$LogType = "System"
$Logs = Get-Eventlog -Logname $LogType -newest 500
$Logs | Foreach-Object {
Out-File -filepath $LogPath -append -Inputobject $_.message; $I++
Write-Host "$I $LogType logs written to $LogPath"
# Invoke-Item $LogPath

Note 1: The key is element is piping the output from $Logs into the Foreach-Object cmdlet.  The script then extracts the $_.message from each item and writes it into a file.

Note 2: To check my logic, you may wish to amend the values for $LogPath and $LogType to suit your computer.

Note 3: To see the contents of the file remove the '#' from the last line.

Researching Parameters for Foreach-Object

This is how I discovered the -Begin and -End parameters for this cmdlet.

Get-Help Foreach-Object -Full

Note 4: The Foreach-Object has this alias: % (Percent sign)

# Foreach-Object -Begin and -End
$LogPath = "C:\temp\application.txt"
$I = 0
$LogType = "Application"
$Logs = Get-Eventlog -Logname $LogType -newest 500
$Logs | % -Begin {Get-Date} -Process {
Out-File -filepath $LogPath -Append -Inputobject $_.message; $I++
} -End {Get-Date}
Write-Host "$I $LogType logs written"

Note 5: Observe how the -Begin and -End parameters write date stamps.

Guy Recommends:  SolarWinds’ Log & Event Management ToolSolarwinds Log and Event Management Tool

LEM will alert you to problems such as when a key application on a particular server is unavailable.  It can also detect when services have stopped, or if there is a network latency problem.  Perhaps this log and event management tool’s most interesting ability is to take corrective action, for example by restarting services, or isolating the source of a maleware attack.

Yet perhaps the killer reason why people use LEM is for its compliance capability, with a little help from you, it will ensure that your organization complies with industry standards such as CISP or FERPA.  LEM is a really smart application that can make correlations between data in different logs, then use its built-in logic to take corrective action, to restart services, or thwart potential security breaches – give LEM a whirl.

Download your FREE trial of SolarWinds Log & Event Management tool.

Comparison of PowerShell Foreach Operator with Foreach-Object Cmdlet

My take on the debate between the simple foreach operator and the more sophisticated Foreach-Object cmdlet is this: if in doubt start with plain foreach.  However, if you need piping, then stick progress to the cmdlet with 'Object' in its name.  If execution speed is important, then read-up on foreach in PowerShell 3.0.

Speed Comparison
It surprised me that the simple foreach operator was an order of magnitude faster than the Foreach-Object cmdlet.

# Comparison of PowerShell foreach operator with the Foreach-Object cmdlet
$BigNum = 1..10000
$GuyMuliplier = 7777
# Plain ForEach section
Write-Host "Foreach operator. Note this statement uses the word ‘in’."
Measure-Command {ForEach($item in $BigNum) {$item * $GuyMultiplier}
                             } | Format-Table Milliseconds -auto
# ForEach-Object section
Write-Host "Note the pipe (|) before Foreach-Object."
Measure-Command {$BigNum | ForEach-Object {$_ * $GuyMultiplier }
                                } | Format-Table Milliseconds -auto

Note 6: This script uses Measure-Command to compare PowerShell’s two looping techniques.  See more on $_.property.

Conclusion: If there is a choice, then the plain ForEach – the one that uses the 'in' – is much faster than the ForEach-Object cmdlet.

For More Information about Foreach Loops – Check About_Foreach

Get-Help about_Foreach

In a nutshell, the Foreach loop) is designed for iterating through a series of values in an array.

More on the differences between 'For' and 'ForEach' Loops ยป

Summary of PowerShell Foreach-Object Cmdlet

The secret of understanding the PowerShell foreach-object is to focus on piping. Also observe that the plain foreach statement contains ‘in’.  Finally, the ForEach-Object cmdlet has parameters such as -Begin.

If you like this page then please share it with your friends


See more Windows PowerShell examples

PowerShell Home   • Foreach loops   • PowerShell Foreach   • Foreach-Object cmdlet

Syntax   • Variables   • -whatIf   • -ErrorAction   • Windows 8 PowerShell   • Free CSV Import Tool

PowerShell Functions   • [System.Math]   • Get-Credential   • Windows PowerShell   • PowerShell 3.0

Please email me if you have a better example script.  Also please report any factual mistakes, grammatical errors or broken links, I will be happy to  correct the fault.