This week I thought we'd have a little fun with the PowerShell console and maybe pick up a few scripting techniques along the way. Today I have a function that changes the foreground and background colors of your PowerShell console to random values. But because you might want to go back to your original settings without completing restarting PowerShell the function allows you to reset to your original values. Oh, and it also supports -Whatif. Here's what I came up with.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
#requires -version 3.0 Function Set-RandomConsole { <# .Synopsis Set the console foreground and background colors to random values. .Description This command will create a random foreground/background color combination for your PowerShell console. Use -Reset to restore settings to the first time you ran the command. The command only works properly in the PowerShell console, NOT the PowerShell ISE. .Parameter Reset Reset console colors to original settings using the values in global variables $savedfg and $savedbg. You must run the command at least once to populate these variables. .Example PS C:\> set-randomconsole Change console colors to a random setting. If this is the first time the command is run, current settings will be saved to global variables $savedfg and $savedbg. .Example PS C:\> set-randomconsole -reset Console colors will be restored to original settings using the values in global variables $savedfg and $savedbg. .Notes Last Updated: July 8, 2014 Version : 0.9 **************************************************************** * DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED * * THOROUGHLY IN A LAB ENVIRONMENT. USE AT YOUR OWN RISK. IF * * YOU DO NOT UNDERSTAND WHAT THIS SCRIPT DOES OR HOW IT WORKS, * * DO NOT USE IT OUTSIDE OF A SECURE, TEST SETTING. * **************************************************************** .Inputs NONE .Outputs NONE #> [cmdletbinding(SupportsShouldProcess)] Param( [switch]$Reset ) Write-Verbose "Starting $($MyInvocation.Mycommand)" #Skip if running in the PowerShell ISE if ($host.Name -match "ISE") { Write-Warning "This command only works in the PowerShell console." #bail out Return } #Save current colors if not already saved if (-Not $global:savedbg) { #saved to a global variable Write-Verbose "Saving current background" $global:savedbg = $host.ui.RawUI.backgroundColor } if (-Not $global:savedfg) { #saved to a global variable Write-Verbose "Saving current foreground" $global:savedfg = $host.ui.RawUI.ForegroundColor } if ($reset) { Write-Verbose "Resetting console" $bg = $global:savedbg $fg = $global:savedfg } else { Write-Verbose "Generating random colors" #set background to a random color $bg = Get-Random ([enum]::GetNames([consolecolor])) #set foreground to a random color other than what is set as foreground $fg = Get-Random ([enum]::GetNames([consolecolor])) | Where {$_ -ne $bg} } Try { Write-Verbose "Applying colors" Write-Verbose "Background = $bg" Write-Verbose "Foreground = $fg" #my code for -WhatiIf $msg = "Background = $bg / Foreground = $fg" if ($PSCmdlet.ShouldProcess( $msg )) { $host.ui.rawui.backgroundcolor= $bg $host.ui.rawui.foregroundcolor = $fg #clear the host to apply the settings #comment this out if trying to trace using the verbose output Clear-Host } #whatif } Catch { Write-Warning "Failed to set console colors. Most likely you tried to reset without first changing anything." } Write-Verbose "Ending $($MyInvocation.Mycommand)" } #end function #define an optional alias Set-Alias -Name src -Value Set-RandomConsole
The function will not work properly in the PowerShell ISE so I've included some code at the beginning to see if it is running in the ISE. If so, the command displays a warning and bails out. This is a scenario where using Return is completely acceptable as I want to return out of the pipeline without doing anything. I could have used a command like this: Return "This command only works in the PowerShell console." but that would have written a string object to the pipeline and I don't want anything to go to the pipeline. Plus, I prefer to use Write-Warning for messages like this.
When you run the command, it tests for the existence of some variables, $savedfg and $savedbg, that are defined in the global scope. You'll notice the use of the global: prefix. If they are not defined, then the assumption is that this is the first time the command has been run and the variables will be defined with the current values of the $host.ui.rawui.foregroundcolor and $host.ui.rawui.backgroundcolor values. Later, if you use -Reset, the command will use these values to restore your original settings.
Otherwise, the command gets a random color for the System.ConsoleColor enumeration for the background and then another random color for the foreground, that is different than the randomly selected background color.
When you look at the code, you will see that I am specifying in the cmdletbinding attribute that the function supports ShouldProcess. That could also be written [cmdletbinding(SupportsShouldProcess=$True)] but that seems redundant to me. Anyway, the command to make the change, $host.ui.rawui.backgroundcolor= $bg, by itself doesn't know anything about ShouldProcess and -WhatIf. But I can add my own code using an If statement.
$msg = "Background = $bg / Foreground = $fg" if ($PSCmdlet.ShouldProcess( $msg )) { $host.ui.rawui.backgroundcolor= $bg $host.ui.rawui.foregroundcolor = $fg #clear the host to apply the settings #comment this out if trying to trace using the verbose output Clear-Host } #whatif
The value for the ShouldProcess() method is the text you see as part of the "...performing operation on target..." message. The text is the target.
All I've done is define a variable, $msg, to make the line of code easier to read. As you can see, it is not that difficult to add your own support for -WhatIf. And now, if you get a little bored, mix it up for a fresh perspective. I've even included an alias, src, in case you have to type in a console where you can't see what you're typing.
Have a terrific weekend.