Search code examples
powershellansi-escapetext-coloringwrite-host

Is there any way to send the nice colouring that write-output achieves through write-host/information etc?


in my function inside a catch block I want to send the get-error details out to the host, and if we are in a terminal, it is nicer to have the different colours that the default formatting produces. However when you push that default formatting through Out-String | Write-Host, we lose the nice colouring.

Is there any way to keep the nice colouring.. especially for get-error as it puts red underlines at the important pieces in very large stacks?

before somone suggests it, I do not want to send the exception to the success stream

function blah {
try {
  throw 'blah'
} catch {
  $_ | Get-Error | Out-String | Write-Host
  $_ | Get-Error # this produce nice coloured text, but it goes to the success stream, which I don't want
  }
}

Solution

  • You can do the following:

    • (Temporarily) set $PSStyle.OutputRendering to 'ANSI' to force the coloring to be preserved.

    • For use via pwsh, the PowerShell (Core) 7 CLI, you can do so conditionally, based on wether the CLI process' stdout is a terminal or not, such as when redirecting the output to a file, in which case you may not want coloring; [Console]::IsOutputRedirected allows making this distinction.

      • Arguably, the PowerShell CLI should make this distinction automatically, analogously to how it already does inside a PowerShell session based on the default value of $PSStyle.OutputRendering, 'Host'.

      • GitHub issue #20170 requests that this be rectified.

    function blah {
      try {
        throw 'blah'
      }
      catch {
        $oldVal = $PSStyle.OutputRendering
        $PSStyle.OutputRendering = 
          [Console]::IsOutputRedirected ? 'PlainText' : 'ANSI'
        $_ | Get-Error | Out-Host
        $PSStyle.OutputRendering = $oldVal
      }
    }
    

    Note:

    • The above confines the conditional coloring to the catch block. If you want to apply it session-globally (to emulate the behavior that fixing the GitHub issue would bring), execute $PSStyle.OutputRendering = [Console]::IsOutputRedirected ? 'PlainText' : 'ANSI' once, at the start of the session.

    • I've replaced Out-String | Write-Host with just Out-Host, which is simpler, and in a CLI call, equivalent (the output goes to stdout in both cases).
      Inside a session, it is possible to capture Write-Host output via the information output stream, whereas Out-Host output can not be captured.