I have been working on this for a while and I cannot find this utilization anywhere. I am using a powershell array and the foreach statement:
@('program 1','program 2','program 3').foreach{winget show $_ -args}
I then want to have a pause between each one so I added ;sleep 1
This does not work. It pauses for 3s (based on this eg.) and then lists the items. What am I missing here?
CodePudding user response:
Indeed it doesn't seem to respect the order, I don't know the technical reason why. You could either use a normal ForEach-Object
'program 1','program 2','program 3' | ForEach-Object {
winget show $_
sleep 1
}
or force the output to go to the console instead of being "buffered"
('program 1','program 2','program 3').ForEach{
winget show $_ | Out-Host
sleep 1
}
CodePudding user response:
Doug Maurer's helpful answer provides effective solutions.
As for an explanation of the behavior you saw:
The intrinsic .ForEach()
method first collects all success output produced by the successive, per-input-object invocations of the script block ({ ... }
) passed to it, and only after having processed all input objects outputs the collected results to the pipeline, i.e. the success output stream, in the form of a [System.Collections.ObjectModel.Collection[psobject]]
instance.
In other words:
Unlike its cmdlet counterpart, the
ForEach-Object
cmdlet, the.ForEach()
method does not emit output produced in its script block instantly to the pipeline.As with any method, success output is only sent to the pipeline when the method returns.
- Note that non-PowerShell .NET methods only ever produce success output (which is their return value) and only ever communicate failure via exceptions, which become statement-terminating PowerShell errors.
By contrast, the following do take instant effect inside a .ForEach()
call's script block:
Suspending execution temporarily, such as via a
Start-Sleep
Forcing instant display (host) output, such as via
Out-Host
orWrite-Host
.- Note that to-host output with
Out-Host
prevents capturing the output altogether, whereasWrite-Host
output, in PowerShell v5 , can only be captured via the information output stream (number6
).
- Note that to-host output with
Writing to an output stream other than the success output stream, such as via
Write-Error
,Write-Warning
orWrite-Verbose -Verbose
.
Alternatively, you may use the foreach
statement, which, like the ForEach-Object
cmdlet, also instantly emits output to the success output stream.