Windows PowerShell Loops
Automating repetitive tasks is what scripting is all about. Therefore, each scripting language needs at least one method for cycling, or looping through a block of instructions. PowerShell provides a rich variety of looping techniques. However, because loops can go spectacularly wrong, I recommend you test a simple PowerShell ‘ForEach’ loop before graduating to more complex constructions in your production scripts.
Types of PowerShell Loop
- Examples of the PowerShell Foreach Loop
- Example 1: PowerShell Foreach Pure Math
- Example 2: PowerShell Foreach To Display Files
- Example 2b: Foreach Piping | Directly Into a {block statement}
- PowerShell While Loop
- Do While Loop
- PowerShell Foreach-Object
- Differences Between For and ForEach Loops
♣
Examples of the PowerShell Foreach Loop
The PowerShell ‘Foreach’ loop is more complex, and has more arguments than the ‘for’ and ‘Do While’ loops. The key feature is that the loop interrogates an array, known as a collection. It then applies a {Statement Block} to each iteration. In addition to the position and the type of bracket, observe the tiny, but crucial keyword – ‘In’.
The secret of understanding PowerShell’s loops is to absorb each element of this syntax:
Foreach ($item in $array_collection) {command_block}.
Example 1: PowerShell Foreach with Pure Math
Here are examples of the ForEach loop, note the word 'In'.
# Simple PowerShell ForEach statement
ForEach ($number in 1,2,3,4,5,6,7,8,9,10) { $number * 7}
# PowerShell Foreach Example
Clear-Host
ForEach ($number in 1..10 ) { $number * 7}
$NumArray = (1,2,3,4,5,6,7,8,9,10)
ForEach ($number in $NumArray ) { $number * 7}
ForEach ($number in 1,2,3,4,5,6,7,8,9,10) { $number * 7}
$NumArray = (1..10)
ForEach ($number in $numArray ) { $number * 7}
Learning Points
Note 1: By creating these five variations, my aim is to give you both perspective and experience of the pure, but simple PowerShell ForEach statement.
Note 2: (1..12) is a convenient method of representing a sequence.
Example 2: PowerShell Foreach to Display Files
In Examples 2a and 2b we are going to make the transition from the explicit ($Item in Collection) {Block Statement} to:
Input stuff using Get-ChildItem, then pipe (|) the output into a {Block Statement}.
Get-ChildItem is just the vehicle for us to investigate aspects of the PowerShell ForEach loop. I chose the root of the C: drive simply because this script will work without modification on 99.9% of computers.
Example 2a Explicit Foreach Get-ChildItem
Using the ForEach Loop
# PowerShell Foreach File Example
Clear-Host
Foreach ($file in Get-Childitem C:\)
{
$file.name
}
Example 2b Foreach-Object Piping | Directly Into the {block statement}
This example employs the ForEach-Object cmdlet, one difference is that it can accept piping, instead of using ($Item in $Collection) clause.
# PowerShell Foreach File Example
Clear-Host
$Path = "C:\Windows\System32\*.dll"
Get-ChildItem $Path | Foreach-Object {
Write-Host $_.Name
}
Learning Points
Note 3: To help you modify my scripts to suit your project I have introduced a $Path variable.
Guy Recommends: A Free Trial of the Network Performance Monitor (NPM) v11.5
SolarWinds’ Network Performance Monitor will help you discover what’s happening on your network. This utility will also guide you through troubleshooting; the dashboard will indicate whether the root cause is a broken link, faulty equipment or resource overload.
What I like best is the way NPM suggests solutions to network problems. Its also has the ability to monitor the health of individual VMware virtual machines. If you are interested in troubleshooting, and creating network maps, then I recommend that you try NPM now.
Download a free trial of Solarwinds’ Network Performance Monitor
Example 3a: A Complex Foreach Example
This pair of examples are just like the above, but introduce slightly more complex scripting. Example 3a contains Foreach with a ($Item in Collection) clause; please contrast with example 3b which exploits the ability of ForEach to receive input via the pipe (|).
# PowerShell ForEach loop to display files in C:\Program files
$Path = "C:\Program Files\"
"{0,10} {1,-24} {2,-2}" -f `
" Size", "Last Accessed", "File Name "
Foreach ($file in Get-Childitem $Path -recurse -force)
{If ($file.extension -eq ".txt")
{
"{0,10} {1,-24} {2,-2}" -f `
$file.length, $file.LastAccessTime, $file.fullname
}
}
Example 3b Foreach-Object piping | directly into the {block statement}
# PowerShell ForEach-Objcet piping into block statement
Clear-Host
$Path = "C:\Program Files\"
Get-Childitem $Path -recurse -force |
Foreach-Object {If ($_.extension -eq ".txt")
{Write-Host $_.fullname
}
}
Note 4: This example uses the same ‘If clause’ as example 3a, its purpose is to filter just .txt files. See PowerShell 3.0 Foreach-Object.
Example 4a: PowerShell Foreach Loop With WMI
Once again, observe the basic structure: Foreach (x in y) {script block}. Where you have more than one drive you need a loop, in this case the ForEach loop.
Basic Example
$disk= Get-WmiObject Win32_LogicalDisk
Foreach ( $drive In $disk ) { "Drive = " + $drive.Name}
Example Incorporating Extra Maths
# Foreach example to display the partitions size [GB]
$disk= Get-WmiObject Win32_LogicalDisk
"Drive Ltr: Size [GB]"
Foreach ( $drive in $disk ) { "Drive = " + $drive.Name + `
" Size = " + [int]($drive.Size/1073741824)}
Example 4b: Another Simple Foreach Using Get-Process
Here is an example using Get-Process. In essence this simple script filters the running processes. Please feel free to modify. Once again, note the tiny word ‘in’.
# PowerShell example listing processes beginning with Task*
Clear-Host
Foreach ($T In Get-Process Task*)
{$T.Name}
Guy Recommends: SolarWinds Engineer’s Toolset v10
This Engineer’s Toolset v10 provides a comprehensive console of 50 utilities for troubleshooting computer problems. Guy says it helps me monitor what’s occurring on the network, and each tool teaches me more about how the underlying system operates.
There are so many good gadgets; it’s like having free rein of a sweetshop. Thankfully the utilities are displayed logically: monitoring, network discovery, diagnostic, and Cisco tools. Try the SolarWinds Engineer’s Toolset now!
Download your fully functional trial copy of the Engineer’s Toolset v10
Example 5: Active Directory
This example conforms to the PowerShell ForEach (condition) {Code Block}; however, there is a preamble of 16 lines where the script connect to Active Directory. Moreover, the {Code Block} is spread over several lines.
N.B. Find $Dom on line 7 and change the value to that of your domain, including the extension.
# ForEach_AD.ps1
# Illustrates using PowerShell ForEach loop to interrogate AD
# IMPORTANT change $Dom ‘value’
# Author: Guy Thomas
#
$Dom = ‘LDAP://DC=YourDom;DC=YourExt’
$Root = New-Object DirectoryServices.DirectoryEntry
Clear-Host
# Create a selector and start searching from the Root of AD
$selector = New-Object DirectoryServices.DirectorySearcher
$selector.SearchRoot = $root
# Filter the users with -Like "CN=Person*". Note the ForEach loop
$adobj= $selector.findall() |
Where-Object {$_.properties.objectcategory -Like "CN=Person*"}
ForEach ($person In $adobj)
{
$prop=$person.properties
Write-host "First name: $($prop.givenname) " `
"Surname: $($prop.sn) User: $($prop.cn)"
}
write-host "`nThere are $($adobj.count) users in the $($root.name) domain"
Learning Points
Note 5: The backtick ` on its own means word-wrap. `n means new line and `t means tab.
Guy Recommends: Free WMI Monitor for PowerShell
Windows Management Instrumentation (WMI) is one of the hidden treasures of Microsoft’s operating systems. Fortunately, SolarWinds have created a Free WMI Monitor so that you can discover these gems of performance information, and thus improve your PowerShell scripts.
Take the guess work out of which WMI counters to use when scripting the operating system, Active Directory, or Exchange Server. Give this WMI monitor a try – it’s free.
Download your free copy of WMI Monitor
PowerShell Loop Output Trick
I have not found it possible to pipe input into loops. Obtaining output was nearly as difficult, however, I have discovered this trick to assign the output to a variable, which we can then manipulate.
$NumArray = (1..12)
$(Foreach ($number In $NumArray ) { $number * 7}) | set-variable 7x
$7x
# Option research properties by removing # on the next line
# $7x | Get-Member
Dejan Milic’s Method (Better)
$NumArray = (1..12)
$7x = @()
Foreach ($number In $NumArray ) { $7x+=$number * 7}
$7x
/\/\o\/\/’s Method (Fantastic)
$7x = 1..12 |% {$_ * 7 }
$7x
I (Guy) envy /\/\o\/\/’s ability to write tight code. That % sign means ‘ForEach’. If you (readers) see anything on the internet by /\/\o\/\/, then you can be sure that it’s top draw code.
®