Home > Enterprise >  While working in Powershell, how do I pause between list items?
While working in Powershell, how do I pause between list items?

Time:09-15

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 or Write-Host.

    • Note that to-host output with Out-Host prevents capturing the output altogether, whereas Write-Host output, in PowerShell v5 , can only be captured via the information output stream (number 6).
  • Writing to an output stream other than the success output stream, such as via Write-Error, Write-Warning or Write-Verbose -Verbose.

Alternatively, you may use the foreach statement, which, like the ForEach-Object cmdlet, also instantly emits output to the success output stream.

  • Related