Setting Console Colours
May 30th, 2016 by Charlie Russel and tagged $Profile, Console Colors, Console Size, PowerShell v5, Windows 10
As I described in my previous post, I always open both an admin and non-admin PowerShell window when I log on to a computer. To tell the two apart, I set the background colour of the Admin window to dark red, with white text, and the non-admin window to a white background with dark blue text. The result is clearly and immediately different, warning me when I’m running as an administrator. To do that, I use the following:
$id = [System.Security.Principal.WindowsIdentity]::GetCurrent() $p = New-Object system.security.principal.windowsprincipal($id) # Find out if we're running as admin (IsInRole). # If we are, set $Admin = $True. if ($p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)){ $Admin = $True } else { $Admin = $False } if ($Admin) { $effectivename = "Administrator" $host.UI.RawUI.Backgroundcolor="DarkRed" $host.UI.RawUI.Foregroundcolor="White" clear-host } else { $effectivename = $id.name $host.UI.RawUI.Backgroundcolor="White" $host.UI.RawUI.Foregroundcolor="DarkBlue" clear-host }
That works great for older versions of the Windows PowerShell console, but starting with PowerShell v5, that can have an unintended side effect. In PowerShell v5, we now have PSReadLine that does context sensitive colouration of the command line. But the default PowerShell console has a dark blue background, with white text. And when I changed the background colour of my non-admin PowerShell window to white, it gets a little hard to read!! So, to fix that, I use Set-PSReadLineOption to change the various kinds of context sensitive colour changes to something that works with a light background. We don’t want to do that for the dark red background of the Admin window, so we’ll need to check which colour we are and adjust accordingly.
First, get the current colour:
$pData = (Get-Host).PrivateData $curForeground = [console]::ForegroundColor $curBackground = [console]::BackgroundColor
You’ll only want to configure the context sensitive colouring options if you’re running on Windows 10 or Server 2016. Prior versions of Windows didn’t have the new system console that comes with Windows 10. So you’ll want to check that the build number is > 10240
$Build = (Get-WmiObject Win32_OperatingSystem).BuildNumber
If $Build -ge 10240, then set the various context sensitive tokens to work with the colour we have.
# PowerShell v5 uses PSReadLineOptions to do syntax highlighting. # Base the color scheme on the background color If ( $curBackground -eq "White" ) { Set-PSReadLineOption -TokenKind None -ForegroundColor DarkBlue -BackgroundColor White Set-PSReadLineOption -TokenKind Comment -ForegroundColor DarkGray -BackgroundColor White Set-PSReadLineOption -TokenKind Keyword -ForegroundColor DarkGreen -BackgroundColor White Set-PSReadLineOption -TokenKind String -ForegroundColor Blue -BackgroundColor White Set-PSReadLineOption -TokenKind Operator -ForegroundColor Black -BackgroundColor White Set-PSReadLineOption -TokenKind Variable -ForegroundColor DarkCyan -BackgroundColor White Set-PSReadLineOption -TokenKind Command -ForegroundColor DarkRed -BackgroundColor White Set-PSReadLineOption -TokenKind Parameter -ForegroundColor DarkGray -BackgroundColor White Set-PSReadLineOption -TokenKind Type -ForegroundColor DarkGray -BackgroundColor White Set-PSReadLineOption -TokenKind Number -ForegroundColor Red -BackgroundColor White Set-PSReadLineOption -TokenKind Member -ForegroundColor DarkBlue -BackgroundColor White $pData.ErrorForegroundColor = "Red" $pData.ErrorBackgroundColor = "Gray" $pData.WarningForegroundColor = "DarkMagenta" $pData.WarningBackgroundColor = "White" $pData.VerboseForegroundColor = "DarkYellow" $pData.VerboseBackgroundColor = "DarkCyan" } elseif ($curBackground -eq "DarkRed") { Set-PSReadLineOption -TokenKind None -ForegroundColor White -BackgroundColor DarkRed Set-PSReadLineOption -TokenKind Comment -ForegroundColor Gray -BackgroundColor DarkRed Set-PSReadLineOption -TokenKind Keyword -ForegroundColor Yellow -BackgroundColor DarkRed Set-PSReadLineOption -TokenKind String -ForegroundColor Cyan -BackgroundColor DarkRed Set-PSReadLineOption -TokenKind Operator -ForegroundColor White -BackgroundColor DarkRed Set-PSReadLineOption -TokenKind Variable -ForegroundColor Green -BackgroundColor DarkRed Set-PSReadLineOption -TokenKind Command -ForegroundColor White -BackgroundColor DarkRed Set-PSReadLineOption -TokenKind Parameter -ForegroundColor Gray -BackgroundColor DarkRed Set-PSReadLineOption -TokenKind Type -ForegroundColor Magenta -BackgroundColor DarkRed Set-PSReadLineOption -TokenKind Number -ForegroundColor Yellow -BackgroundColor DarkRed Set-PSReadLineOption -TokenKind Member -ForegroundColor White -BackgroundColor DarkRed $pData.ErrorForegroundColor = "Yellow" $pData.ErrorBackgroundColor = "DarkRed" $pData.WarningForegroundColor = "Magenta" $pData.WarningBackgroundColor = "DarkRed" $pData.VerboseForegroundColor = "Cyan" $pData.VerboseBackgroundColor = "DarkRed" } }
Finally, let’s make sure that console window is the right size, and while we’re at it, set the window title. (This is a workaround for a PITA bug in recent builds of Windows 10/Server 2016 that seems to have problems setting the console window size and keeping it!)
$host.ui.rawui.WindowTitle = $effectivename + "@" + $HostName +" >" $Host.UI.RawUI.WindowSize = New-Object System.Management.Automation.Host.Size(120,40)
Now, with all of this, you have effective, context-sensitive, command-line colouring of your PowerShell windows.
ETA: The Console as we know it is completely broken in recent builds of Windows 10. As of August, 2018, you can’t effectively set the background color of the console and have it stick, plus they completely changed the behaviour of Set-PSReadlineOption by changing the parameters, and removing support for -TokenKind with FG/BG colors to totally break this script. Sigh.
Posted in $Profile, Annoyances, Console, PowerShell, Windows 10, Windows Server 2016, WMI | Comments Off on Setting Console Colours