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 writt
This way:
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
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
}
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.
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 ){
$status | write-host -fore green -back red; #send a status msg to the console
$status | write-output; #send a status object down the pipe
}
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.
I know this post is ancient, but this could come handy to someone out there.
I wanted to change colors and the accepted answer was not the best solution. In my eyes, the following code is better solution as it takes advantage of the native PowerShell functionality:
EDIT:
# Print User message using String Array $message
function PrintMessageToUser {
param(
[Parameter( `
Mandatory=$True, `
Valuefrompipeline = $true)]
[String]$message
)
begin {
$window_private_data = (Get-Host).PrivateData;
# saving the original colors
$saved_background_color = $window_private_data.VerboseBackgroundColor
$saved_foreground_color = $window_private_data.VerboseForegroundColor
# setting the new colors
$window_private_data.VerboseBackgroundColor = 'Black';
$window_private_data.VerboseForegroundColor = 'Red';
}
process {
foreach ($Message in $Message) {
# Write-Host Considered Harmful - see http://www.jsnover.com/blog/2013/12/07/write-host-considered-harmful/
# first way how to correctly write it
#Write-host $message;
Write-Verbose -Message $message -Verbose;
# second correct way how to write it
#$VerbosePreference = "Continue"
#Write-Verbose $Message;
}
}
end {
$window_private_data.VerboseBackgroundColor = $saved_background_color;
$window_private_data.VerboseForegroundColor = $saved_foreground_color;
}
} # end PrintMessageToUser