Is there a way to specify a font color when using write-output

I have a powershell script that gives some status output via write-output. I am intentionally not using write-host because the output may be captured and written to a logfile like this:

./myscript.ps1 | out-file log.txt 

But if the output is not redirected it would be nice to have colored output on the console, because the script is producing a lot of different status messages. I know that colored output is possible with write-host but the status messages should be pipeable. Any ideas how to solve this?

asked Jan 10, 2011 at 14:23 1,734 1 1 gold badge 19 19 silver badges 37 37 bronze badges

MS suggests using write-host technet.microsoft.com/en-us/library/ff406264.aspx, but I understand your worries

Commented Jan 10, 2011 at 14:47 This sucks because Write-Host has a -ForegroundColor argument, but Write-Output does not. Commented Sep 1, 2018 at 20:22

@DennisG The issue is when you are display a Psobject using Write-Host , it will look like this @ which is horrible to look at

Commented Sep 1, 2018 at 20:23

6 Answers 6

I have tried this extra function and it basically works fine:

function Write-ColorOutput($ForegroundColor) < # save the current color $fc = $host.UI.RawUI.ForegroundColor # set the new color $host.UI.RawUI.ForegroundColor = $ForegroundColor # output if ($args) < Write-Output $args >else < $input | Write-Output ># restore the original color $host.UI.RawUI.ForegroundColor = $fc > # test Write-ColorOutput red (ls) Write-ColorOutput green (ls) ls | Write-ColorOutput yellow 

The result of this particular test is a little bit funny though: we really get lines in red, green and yellow but the table header is in red, i.e. the color of the the first call of the function.

answered Jan 10, 2011 at 14:44 Roman Kuzmin Roman Kuzmin 41.6k 11 11 gold badges 100 100 silver badges 120 120 bronze badges

That won't work so good in ISE or other non-console-based hosts. :-) You might try $host.UI.RawUI.ForegroundColor instead.

Commented Jan 10, 2011 at 16:58

@Keith, you are definitely right (even though the author asks about console). I have updated the code.

Commented Jan 10, 2011 at 17:10

[Console]::ForegroundColor is actually better, because $host.UI.RawUI.ForegroundColor does not do what you are expecting in powershell_ise.

Commented Nov 10, 2014 at 4:03
function Green < process < Write-Host $_ -ForegroundColor Green >> function Red < process < Write-Host $_ -ForegroundColor Red >> Write-Output "this is a test" | Green Write-Output "this is a test" | Red 

enter image description here

answered Feb 20, 2019 at 3:41 Francesco Mantovani Francesco Mantovani 11.6k 19 19 gold badges 91 91 silver badges 150 150 bronze badges

This simply redirects the output to Write-Host, so the effect is the same as if you used Write-Host in the first place, and crucially doesn't resolve the issue of the output being redirected to a file. Using this method, if you redirect the output of your script to a file, any text returned using this method is displayed on screen, not outputted to the file.

Commented Jan 9, 2020 at 9:43

Separate the results on the pipeline from the status messages in the console.

E.g., use a function like this in your script:

function write-status( $status )

I would also recommend you use one of the following cmdlets over write-host for outputting status messages from your scripts:

The appearance of these status messages will vary depending on the cmdlet used. In addition, the user can disable specific levels of status using the $(warning|error|verbose|debug)preference variables, or capture specific status messages using the -(warning|error|verbose|debug)variable common cmdlet parameters.

answered Jan 10, 2011 at 15:57 1,151 7 7 silver badges 8 8 bronze badges Not very nice because all message are shown twice when the output is not piped to a file. Commented Jan 13, 2011 at 13:03

I agree, any function that uses this will be unsuitable for interactive use. The only decent way to capture anything you've write-hosted is Start-Transcript.

Commented Nov 12, 2014 at 9:36

I had the same problem, so I share my solution which I think works quite well:

Write-ColorOutput "Hello" Green Black -NoNewLine Write-ColorOutput " World" Red 

This is the Cmdlet to use it

function Write-ColorOutput < [CmdletBinding()] Param( [Parameter(Mandatory=$False,Position=1,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)][Object] $Object, [Parameter(Mandatory=$False,Position=2,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)][ConsoleColor] $ForegroundColor, [Parameter(Mandatory=$False,Position=3,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)][ConsoleColor] $BackgroundColor, [Switch]$NoNewline ) # Save previous colors $previousForegroundColor = $host.UI.RawUI.ForegroundColor $previousBackgroundColor = $host.UI.RawUI.BackgroundColor # Set BackgroundColor if available if($BackgroundColor -ne $null) < $host.UI.RawUI.BackgroundColor = $BackgroundColor ># Set $ForegroundColor if available if($ForegroundColor -ne $null) < $host.UI.RawUI.ForegroundColor = $ForegroundColor ># Always write (if we want just a NewLine) if($Object -eq $null) < $Object = "" >if($NoNewline) < [Console]::Write($Object) >else < Write-Output $Object ># Restore previous colors $host.UI.RawUI.ForegroundColor = $previousForegroundColor $host.UI.RawUI.BackgroundColor = $previousBackgroundColor > 
answered May 24, 2018 at 14:06 841 10 10 silver badges 10 10 bronze badges

I have the same problem, I need to log the output by screen with colors in interactive way and send that output to a file in autometed way.

My solution is to use a parameter to indicate the output type ('Screen' or 'File'), then the function can decide how to render de output.

function Write-Color([String[]]$Text, [ConsoleColor[]]$Color, [ConsoleColor]$BackgroundColor = ([console]::BackgroundColor), $OutputType='Screen') < switch ($OutputType) < 'Screen' < for ($i = 0; $i -lt $Text.Length; $i++) < Write-Host $Text[$i] -Foreground $Color[$i] -NoNewLine -BackgroundColor $BackgroundColor >Write-Host break > 'File' < # Assuming $OFS built-in Variable is an space write-output "$Text" break >Default < throw '$OutputType must be "Screen" or "File".' >> > $CodeBlock = < param ($OutputType) Write-Color -T "=== STARTING ===" -C Cyan -B Gray -O $OutputType Write-Color -T 'Date: ', (Get-Date).ToString('yyyy-MM-dd hh:mm:ss') -C Green, Yellow -O $OutputType Write-Color -T 'Processing..' -C Cyan -O $OutputType Write-Color -T 'Date: ', (Get-Date).AddSeconds(3).ToString('yyyy-MM-dd hh:mm:ss') -C Green, Yellow -O $OutputType Write-Color -T "=== ENDING ===" -C Cyan -B Gray -O $OutputType >$Dir = 'D:\Tmp' # Set your output directory #### Screen Test #### & $CodeBlock -OutputType 'Screen' & $CodeBlock -OutputType 'File' ### File Test #### # This file have unwanted newlines, notice the IO redirection with "*>" & $CodeBlock -OutputType 'Screen' *> "$Dir\Screen.log" & $CodeBlock -OutputType 'File' > "$Dir\File.log"