Published in Articles on by Michiel van Oosterhout ~ 6 min read
Last December we looked at Console Window Host's 4-bit color palette, and at how to configure a color theme. We mentioned the default color settings for screen text and screen background, but we conveniently ignored the default color settings for popup text and background. Let's finish today what we started back in December!
Windows Command Processor popups
Windows Command Processor maintains a history of entered command lines. You can edit the previous command line by pressing the
The colors used by this and other popups (try F2, F4, or F9) are stored in the Windows Registry. The Windows PowerShell script below sets the color palette entries 7 and 1 for the text and background respectively:
# Ensure the registry key exists
$path = "HKCU:\Console"
if (-not (Test-Path -Path $path))
{
$key = New-Item -Force -ItemType Directory -Path $path
}
# Set the popup text and background
$value = New-ItemProperty -Force -Name "PopupColors" -Path $path -PropertyType "DWord" -Value 0x17
The result is shown in the screenshot below:

Windows PowerShell output
Unlike the syntax highlighting of command lines (input), the colors of the output in Windows PowerShell is configured via an ephemeral automatic variable called $Host
.
Accessing the Console API
We can use $Host.UI.RawUI
to get access to (part of) the Windows Console API. We can get the title of the Window for example ($Host.UI.RawUI.WindowTitle
), or the size of the cursor ($Host.UI.RawUI.CursosSize
). We can even changes these, but the changes do not persist after the session has ended.
We can also get the current screen buffer's attributes, translated to System.ConsoleColor
values. So if we run cmd /c color 17
, then $Host.UI.RawUI.BackgroundColor
is DarkBlue
, and $Host.UI.RawUI.BackgroundColor
is Gray
.
Output streams
If the PSReadLine module provides theming for input, then $Host.PrivateData
provides theming for output. In Windows PowerShell there are 6 numbered output streams:
- Success (
stdout
) - Error (
stderr
) - Warning
- Verbose
- Debug
- Information
For the streams numbered 2, 3, 4, and 5 there are corresponding ForegroundColor
and BackgroundColor
properties on $Host.PrivateData
.
Because the $Host
variable is ephemeral we must set the properties in every Windows PowerShell session. We do this by adding code to the Windows PowerShell profile. Since the profile may already contain some code, we must take care to add the additional code to the end of the file:
# Ensure the profile exists
$directoryPath = Split-Path -Path $Profile -Parent
If (-not (Test-Path -Path $directoryPath))
{
$directory = New-Item -ItemType Directory -Path $directoryPath
}
If (-not (Test-Path -Path $profile))
{
$file = New-Item -ItemType File -Path $profile
}
# Ensure new code is separate from existing code
"" | Add-Content -Path $profile
"" | Add-Content -Path $profile
# Define the colors
$colors = @{
"Debug" = "DarkMagenta"
"Verbose" = "DarkBlue"
"Warning" = "DarkYellow"
"Error" = "DarkRed"
}
# Add code to set the foreground colors for output streams
foreach ($entry in $colors.GetEnumerator())
{
$level = $entry.Key
$color = $entry.Value
$code = "`$Host.PrivateData.${level}ForegroundColor = [System.ConsoleColor]::$color"
$code | Add-Content -Path $profile
}
The color palette entries should be chosen such that there is enough contrast to read the output against the host's background color. Otherwise, set BackgroundColor
for a stream as well.
To test these settings, we first need to understand how to write to streams. Each stream has its own Write-
cmdlet, and each cmdlet has its own parameters and behavior.
Stream | Cmdlet Write- |
Value parameter | Target | Action parameter | Preference variable |
---|---|---|---|---|---|
1 | Output |
InputObject |
pipeline | ||
2 | Error |
Message |
stream | ErrorAction |
$ErrorActionPreference |
3 | Warning |
Message |
stream | WarningAction |
$WarningPreference |
4 (1) | Verbose |
Message |
stream | Verbose |
$VerbosePreference |
5 (2) | Debug |
Message |
stream | Debug (3) |
$DebugPreference |
6 | Information |
MessageData |
stream | InformationAction |
$InformationPreference |
6 | Host (4) |
Object |
stream | InformationAction |
$InformationPreference |
- The host prepends
VERBOSE:
to the output in stream 4. - The host prepends
DEBUG:
to the output in stream 5. - In interactive mode
-Debug
overrides$DebugPreference
withInquire
. Write-Host
does not honorSilentlyContinue
, as it will always write to the stream.
There are also methods on $Host.UI
(see PSHostUserInterface
class) that we can use to write directly to the screen buffer. We should only use these for testing purposes, as they completely bypass the streams and igore action parameters and preference variables. The Windows PowerShell script below can be used to test our new output theme:
Clear-Host
$Host.UI.WriteDebugLine("This is debug output")
$Host.UI.WriteVerboseLine("This is verbose output")
$Host.UI.WriteWarningLine("This is warning output")
$Host.UI.WriteErrorLine("This is error output")
The result is shown in the screenshot below:

Progress
The output streams shown in the previous section may seem like a diversion from the topic of CLI popups, except that there is one more stream in Windows PowerShell, the progress stream, which behaves like a popup.
The Progress stream is used for messages that communicate progress in longer running commands and scripts. Use the
Write-Progress
cmdlet to explicitly write messages to this stream. The Progress stream doesn't support redirection.
The colors used by the progress stream popup can also be configured via $Host.PrivateData
. The Windows PowerShell script below adds the required code to the profile:
# Ensure the profile exists
$directoryPath = Split-Path -Path $Profile -Parent
If (-not (Test-Path -Path $directoryPath))
{
$directory = New-Item -ItemType Directory -Path $directoryPath
}
If (-not (Test-Path -Path $profile))
{
$file = New-Item -ItemType File -Path $profile
}
# Ensure new code is separate from existing code
"" | Add-Content -Path $profile
"" | Add-Content -Path $profile
# Define the colors
$colors = @{
"Foreground" = "Gray"
"Background" = "DarkBlue"
}
# Add code to set the foreground and background colors for the progress popup
foreach ($entry in $colors.GetEnumerator())
{
$type = $entry.Key
$color = $entry.Value
$code = "`$Host.PrivateData.Progress${type}Color = [System.ConsoleColor]::$color"
$code | Add-Content -Path $profile
}
The Windows PowerShell script below can be used to test the colors of the progress stream:
Clear-Host
for ($i = 1; $i -le 100; $i++ ) {
Write-Progress -Activity "Activity" -Status "$i% complete" -PercentComplete $i
Start-Sleep -Milliseconds 250
}
The result is shown in the screenshot below:

Summary
With a color theme in place, we can configure some output colors. Windows Command Processor uses the Windows Console Host's popup colors for some of its output, like the command line history. Windows PowerShell allows us to configure colors for some of its output streams. The debug, verbose, warning, and error output streams are regular output streams. The progress output stream behaves more like a popup.