After far too long of not doing it, I’ve started using the full version of PowerShell commands (i.e. no aliases) and their parameters. Along with this, I’m dropping use of the '| ’ pipeline character from my scripts. Here’s my problem.
I used to use ForEach in something like the format below as an example:
Sorry, I didn’t word that good. What i mean is that if i can, i find
ForEach ($user in $users) {
…
…
…
}
looks better than than
$users | ForEach-Object {
…
…
…
}
So if i don’t need to use the the ’ | ’ character i won’t.
Best practices are to use the full command name and properties, but I’m not certain how i’d do this with ForEach-Object other than use the ’ | ’ symbol, since -inputobject doesnt seem to work the way i thought it would.
Here foreach is a keyword, for more information about this, check Get-Help about_Foreach.
This method requires that all objects are stored in the $Users variable and if there are many it could be heavy on memory usage.
Here is an example using the Cmdlet Foreach-Object (which can also be referenced to by its two aliases foreach and %):
In this example, Get-ADUser will immediately send each user retrieved from AD to Foreach-Object that can start to process the objects as they are retrieved.
This is a leaner approach since only the objects currently being processed are stored in memory and we don’t have to wait for AD to return all objects before we start processing them.
For more information on the Cmdlet Foreach-Object, see Get-Help Foreach-Object.
Ah, okay, thats starting to make sense. So if i understand right ForEach-Object would only ever normally be used when it is prefixed with an object that is piped to it, or if you wanted to pass an entire object in one via -inputobject?
I think the thing that’s really thrown me is that ForEach is listed as an alias for ForEach-Object in PowerShell.
PS C:\Windows\system32> Get-Alias -Name foreach
CommandType Name Source
Alias foreach -> ForEach-Object
So i thought it would be possible for me also to use the same format of command I’d used in ForEach. I was searching for the property of the ForEach-Object command to use that would allow me to do that.
ForEach-Object only works with pipeline input. Even if you could use it as the first or only command in a pipeline, it would be far slower than using the foreach keyword.
That said, I wouldn’t recommend going to either extreme (using only $users | ForEach-Object or only foreach ($user in $users)). These have different performance characteristics, with the keyword typically being faster but at the expense of requiring more memory. If you force yourself into never using the pipeline, you’re eventually going to run into OutOfMemoryExceptions when handling large sets of data.
One more thing, with
foreach ($object in $collection) {}
but not with
$objects | ForEach-Object {}
you can use the continue keyword to jump to the next item in the collection like you can with the various looping constructs.