Reputation: 3109
I've got the following code:
function f()
{
begin{$count=0}
process{$count+=10}
end{$count}
}
1..10|f # OK
1..10|%{
begin{$count=0}
process{$count+=10}
end{$count}
} # Error
The first "f" call succeeds, while the %{} block shows error:
100
% : The script block cannot be invoked because it contains more than one clause. The Invoke() method can only be used on script blocks that contain a single clause.
At D:\Untitled1.ps1:13 char:7
+ 1..10|%{
+ ~~
+ CategoryInfo : InvalidOperation: (:) [ForEach-Object], PSInvalidOperationException
+ FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.ForEachObjectCommand
But why? ForEach-Object
doesn't support begin
/process
/end
blocks?
Upvotes: 3
Views: 4232
Reputation: 27473
A cool thing is, you can do it without specifying the parameters, and it works, using -process and -remainingscripts behind the scenes.
1..10 | ForEach {$count=0} {$count+=10} {$count}
100
Upvotes: 2
Reputation: 171
As an addendum, just a small point if you like to structure your code for ease of reading. The continuation tick ("`") is important - as I just found out to some cost to myself!
Get-Content -Path $SelectedFiles | ForEach-Object `
-Begin {
#- Do Begin stuff -----
} `
-Process {
#- Do Process stuff
} `
-End {
#- Do End stuff
}
#- EndOf: ForEach is here -----
#- NB! Continuation tick "`" must be preceded by space & be LAST character on line!!!!!
To help in the ISE, the colour of the parameters (Begin, Process, End) should be the same as other parameters (my parameters are black) when correctly identified. Play with the above code in the ISE, put a space after a tick, don't have a space before a tick, etc. I didn't realise how important a 'space' could be - grin! Good luck! Hope this helps another beginner like me.
Upvotes: 2
Reputation: 174555
ForEach-Object
takes the individual blocks as separate named parameters.
In your case, that would be:
1..10 |ForEach-Object -Begin {$count=0} -Process {$count+=10} -End {$count}
This is well documented in the help files - from Get-Help ForEach-Object -Parameter *
:
-Begin <ScriptBlock>
Specifies a script block that runs before processing any input objects.
Required? false
Position? named
Default value None
Accept pipeline input? false
Accept wildcard characters? false
-End <ScriptBlock>
Specifies a script block that runs after processing all input objects.
Required? false
Position? named
Default value None
Accept pipeline input? false
Accept wildcard characters? false
<# ... #>
-Process <ScriptBlock[]>
Specifies the operation that is performed on each input object. Enter a script
block that describes the operation.
Required? true
Position? 1
Default value None
Accept pipeline input? false
Accept wildcard characters? false
Upvotes: 8