I came across a post the other day that explained differences when using the ForEach enumerator and the ForEach-Object cmdlet. They both essentially do the same thing but as the post mentions there are potential performance differences. One other difference I want to highlight is that the ForEach enumerator doesn't write to the pipeline at the end.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
By that, I mean a command like this will fail:
[cc lang="DOS"]
PS C:\> foreach ($i in (1..10)) {$i*2} | out-file $env:temp\data.txt
An empty pipe element is not allowed.
At line:1 char:33
+ foreach ($i in (1..10)) {$i*2} | <<<< $env:temp\out-file data.txt
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : EmptyPipeElement
[/cc]
Of course there are workarounds but you have to apply them to every pipelined object in the {}. Compare that to using ForEach-Object.
[cc lang="DOS"]
PS C:\> 1..10 | foreach-object {$_*2} | out-file $env:temp\data.txt
[/cc]
With the enumerator you get to name your own variable. With ForEach-Object you use the $_ placeholder. Personally, I think of the ForEach enumerator as a legacy construct from the VBScript days. That's not to say you should never use it, but you need to look at the bigger picture of what you are attempting to accomplish and make sure you are doing it the "PowerShell" way.