PowerShell output is crossing between functions

前端 未结 1 967
挽巷
挽巷 2020-11-22 16:31

I am writing a PowerShell script in version 5.1 on Windows 10 that gets certain pieces of information about a local system ( and eventually its subnets ) and outputs them in

相关标签:
1条回答
  • 2020-11-22 17:05

    tl; dr:

    Force synchronous output to the console by using a formatting cmdlet explicitly:

    getUsersAndGroups | Out-Host
    getRunningProcesses | Out-Host
    

    Note: You can alternatively use one of the Format-* cmdlets, which also forces synchronous output; e.g., getUsersAndGroups | Format-Table.

    Note that this is primarily a display problem, and you do not need this workaround for capturing output in a file or passing it on through the pipeline.

    However, sending to Out-Host means that the commands' output can no longer be captured or redirected; see this answer for a - suboptimal - workaround.


    It's helpful to demonstrate the problem with an MCVE (Minimal, Complete, and Verifiable Example):

    Write-Host "-- before"
    [pscustomobject] @{ one = 1; two = 2; three = 3 }
    Write-Host "-- after"
    

    In PSv5+, this yields:

    -- before
    
    -- after
    one two three
    --- --- -----
      1   2     3
    

    What happened?

    • The Write-Host calls produced output synchronously.

      • It is worth noting that Write-Host bypasses the normal success output stream and (in effect) writes directly to the console - mostly, even though there are legitimate uses, Write-Host should be avoided.
    • The implicit output - from not capturing the output from statement [pscustomobject] @{ one = 1; two = 2; three = 3 } - was unexpectedly not synchronous:

      • A blank line was initially produced.
      • All actual output followed the final Write-Host call.

    This helpful answer explains why that happens; in short:

    • Implicit output is formatted based on the type of objects being output; in the case at hand, Format-Table is implicitly used.

    • In Psv5+, implicitly applied Format-Table now waits up to 300 msecs. in order to determine suitable column widths.

      • Note, however, that this only applies to output objects for whose type table-formatting instructions are not predefined; if they are, they determine the column widths ahead of time, and no waiting occurs.
      • To test whether a given type with full name <FullTypeName> has table-formatting data associated with it, you can use the following command:

        # Outputs $true, if <FullTypeName> has predefined table-formatting data.
        Get-FormatData <FullTypeName> -PowerShellVersion $PSVersionTable.PSVersion |
          Where-Object { 
            $_.FormatViewDefinition.Control.ForEach('GetType') -contains [System.Management.Automation.TableControl] 
          }
        
    • Unfortunately, that means that subsequent commands execute inside that time window and may produce unrelated output (via pipeline-bypassing output commands such as Write-Host) or prompt for user input before Format-Table output starts.

    The problematic behavior is discussed in this GitHub issue; while there's still hope for a solution, there has been no activity in a long time.


    Note: This answer originally incorrectly "blamed" the PSv5+ 300 msec. delay for potentially surprising standard output formatting behavior (namely that the first object sent to a pipeline determines the display format for all objects in the pipeline, if table formatting is applied - see this answer).

    0 讨论(0)
提交回复
热议问题