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-Objectcmdlet, 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-SleepForcing instant display (host) output, such as via
Out-HostorWrite-Host.- Note that to-host output with
Out-Hostprevents capturing the output altogether, whereasWrite-Hostoutput, 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-WarningorWrite-Verbose -Verbose.
Alternatively, you may use the foreach statement, which, like the ForEach-Object cmdlet, also instantly emits output to the success output stream.
