Last active
October 16, 2024 01:47
-
-
Save blakedrumm/0842e0c98cdbdf2f5bc1657f38422695 to your computer and use it in GitHub Desktop.
Enhance your PowerShell scripts with Write-Console for displaying messages with optional timestamps and customizable colors. Utilize dynamic rainbow mode to create colorful, segmented outputs where each character has a unique color, ensuring no consecutive duplicates. Improve readability and organization in your console applications effortlessly…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Provides advanced console output functionality with customizable timestamps and colorization options. | |
.DESCRIPTION | |
This script contains the `Write-Console` function to enhance PowerShell console output. | |
It offers features such as customizable timestamps, colored text, and segmented messages with advanced formatting. | |
A "Rainbow" mode is included, which applies unique colors to each character, improving readability and visual organization. | |
.EXAMPLE | |
Write-Console -Text "Process started successfully." -ForegroundColor Green -BackgroundColor Black -TimestampColor White -SeparatorColor Cyan | |
Display a simple colored message with a timestamp | |
.EXAMPLE | |
$messageSegments = @( | |
@{ Text = "Error: "; ForegroundColor = 'Red' }, | |
@{ Text = "Invalid input detected."; ForegroundColor = 'White'; BackgroundColor = 'DarkRed' } | |
) | |
Write-Console -MessageSegments $messageSegments -SeparatorColor Magenta -NoTimestamp | |
Display a complex, colorized message without a timestamp | |
.EXAMPLE | |
Write-Console -Text "This is pretty cool" -ForegroundColor Rainbow -TimestampColor Rainbow -SeparatorColor Rainbow -NoNewLine | |
Display a rainbow-colored message without a newline at the end | |
.NOTES | |
Author: Blake Drumm | |
Date Created: 2024-10-05 | |
Date Modified: 2024-10-14 | |
- Ensure the console supports the specified colors. | |
- The `-NoTimestamp` switch omits the timestamp from the output. | |
- The `-NoNewLine` switch omits the newline after the message. | |
- When using arrays for parameters like `-MessageSegments`, ensure parameter names are explicitly provided to avoid positional binding issues. | |
- The "Rainbow" feature cycles through a predefined set of colors for each character in the output. | |
- This script adheres to PowerShell best practices, including structured documentation, parameter validation, and examples for ease of use. | |
.LINK | |
https://gist.github.com/blakedrumm/0842e0c98cdbdf2f5bc1657f38422695 | |
.LINK | |
https://blakedrumm.com/ | |
#> | |
function Time-Stamp | |
{ | |
$TodaysDate = [DateTime]::Now | |
return "$($TodaysDate.ToShortDateString()) $($TodaysDate.ToLongTimeString())" | |
} | |
function Write-Console | |
{ | |
[CmdletBinding()] | |
param ( | |
# ===================================================== | |
# Parameters for the Write-Console Function | |
# ===================================================== | |
# Optional parameter for a simple text message | |
[Parameter(Mandatory = $false)] | |
[string]$Text, | |
# Optional parameter for an array of message segments (for colorized output) | |
[Parameter(Mandatory = $false)] | |
[Array]$MessageSegments, | |
# Optional foreground color for the timestamp text | |
[Parameter()] | |
[ValidateSet( | |
'Black', 'DarkBlue', 'DarkGreen', 'DarkCyan', 'DarkRed', 'DarkMagenta', | |
'DarkYellow', 'Gray', 'DarkGray', 'Cyan', 'Green', 'Red', | |
'Magenta', 'Yellow', 'White', 'Default', 'Rainbow')] | |
[string]$TimestampColor, | |
# Optional background color for the timestamp | |
[Parameter()] | |
[ValidateSet( | |
'Black', 'DarkBlue', 'DarkGreen', 'DarkCyan', 'DarkRed', 'DarkMagenta', | |
'DarkYellow', 'Gray', 'DarkGray', 'Cyan', 'Green', 'Red', | |
'Magenta', 'Yellow', 'White')] | |
[string]$TimestampBackgroundColor, | |
# Optional foreground color for the text (used with -Text parameter) | |
[Parameter()] | |
[ValidateSet( | |
'Black', 'DarkBlue', 'DarkGreen', 'DarkCyan', 'DarkRed', 'DarkMagenta', | |
'DarkYellow', 'Gray', 'DarkGray', 'Cyan', 'Green', 'Red', | |
'Magenta', 'Yellow', 'White', 'Default', 'Rainbow')] | |
[string]$ForegroundColor, | |
# Optional background color for the text (used with -Text parameter) | |
[Parameter()] | |
[ValidateSet( | |
'Black', 'DarkBlue', 'DarkGreen', 'DarkCyan', 'DarkRed', 'DarkMagenta', | |
'DarkYellow', 'Gray', 'DarkGray', 'Cyan', 'Green', 'Red', | |
'Magenta', 'Yellow', 'White')] | |
[string]$BackgroundColor, | |
# Optional foreground color for the separator text | |
[Parameter()] | |
[ValidateSet( | |
'Black', 'DarkBlue', 'DarkGreen', 'DarkCyan', 'DarkRed', 'DarkMagenta', | |
'DarkYellow', 'Gray', 'DarkGray', 'Cyan', 'Green', 'Red', | |
'Magenta', 'Yellow', 'White', 'Default', 'Rainbow')] | |
[string]$SeparatorColor, | |
# Switch to suppress the timestamp output | |
[Parameter(Mandatory = $false)] | |
[switch]$NoTimestamp, | |
# Switch to suppress the newline after the message | |
[Parameter(Mandatory = $false)] | |
[switch]$NoNewLine | |
) | |
# GitHub Gist link: https://gist.github.com/blakedrumm/0842e0c98cdbdf2f5bc1657f38422695 | |
# ===================================================== | |
# Initialize Variables | |
# ===================================================== | |
# Initialize the separator as an empty string | |
$separator = "" | |
# Set the log file path (adjust this path as needed) | |
$logFilePath = "C:\Temp\script.log" | |
# Ensure the log directory exists | |
$logDirectory = [System.IO.Path]::GetDirectoryName($logFilePath) | |
if (!(Test-Path -Path $logDirectory)) | |
{ | |
# Create the directory if it doesn't exist | |
New-Item -ItemType Directory -Path $logDirectory -Force | Out-Null | |
} | |
# Initialize the script-scoped log buffer if not already initialized | |
if (-not ($script:logBuffer)) | |
{ | |
$script:logBuffer = "" | |
} | |
# ===================================================== | |
# Helper Function to Generate Unique Color Index | |
# ===================================================== | |
function Get-UniqueColorIndex | |
{ | |
param ( | |
[int]$Min = 0, | |
[int]$Max = 7 | |
) | |
# Initialize a script-scoped variable to store the previous color index | |
if (-not ($script:previousColorIndex -ne $null)) | |
{ | |
$script:previousColorIndex = -1 | |
} | |
do | |
{ | |
# Generate a new random color index | |
$newColorIndex = Get-Random -Minimum $Min -Maximum $Max | |
} | |
while ($newColorIndex -eq $script:previousColorIndex) | |
# Update the previous color index | |
$script:previousColorIndex = $newColorIndex | |
return $newColorIndex | |
} | |
# ===================================================== | |
# Timestamp Handling Section | |
# ===================================================== | |
# Check if the NoTimestamp switch is NOT set | |
if (-not $NoTimestamp) | |
{ | |
# Generate the timestamp using the Time-Stamp function and trim any whitespace | |
$timestamp = (Time-Stamp).Trim() | |
# Append the timestamp to the log buffer | |
$script:logBuffer += $timestamp | |
# Handle Rainbow for TimestampColor | |
if ($TimestampColor -eq 'Rainbow') | |
{ | |
# Define the rainbow color sequence | |
$rainbowColors = @('Red', 'DarkYellow', 'Yellow', 'Green', 'Cyan', 'DarkMagenta', 'Magenta') | |
# Iterate through each character and apply a color | |
foreach ($char in $timestamp.ToCharArray()) | |
{ | |
# Get a unique color index | |
$colorIndex = Get-UniqueColorIndex -Min 0 -Max 7 | |
$currentColor = $rainbowColors[$colorIndex % $rainbowColors.Count] | |
# Prepare parameters for Write-Host for each character | |
$charParams = @{ | |
'Object' = $char | |
'NoNewline' = $true | |
'ForegroundColor' = $currentColor | |
} | |
# Include BackgroundColor only if it's specified | |
if ($PSBoundParameters.ContainsKey('TimestampBackgroundColor') -and $TimestampBackgroundColor) | |
{ | |
$charParams['BackgroundColor'] = $TimestampBackgroundColor | |
} | |
# Output the character with the specified color | |
Write-Host @charParams | |
} | |
} | |
else | |
{ | |
# Prepare parameters for Write-Host to output the timestamp | |
$timeStampParams = @{ | |
'Object' = $timestamp # The timestamp text | |
'NoNewline' = $true # Keep the cursor on the same line | |
} | |
# If a foreground color for the timestamp is provided, include it | |
if ($PSBoundParameters.ContainsKey('TimestampColor') -and $TimestampColor -and $TimestampColor -ne 'Default') | |
{ | |
$timeStampParams['ForegroundColor'] = $TimestampColor | |
} | |
# If a background color for the timestamp is provided, include it | |
if ($PSBoundParameters.ContainsKey('TimestampBackgroundColor') -and $TimestampBackgroundColor) | |
{ | |
$timeStampParams['BackgroundColor'] = $TimestampBackgroundColor | |
} | |
# Output the timestamp with the specified colors (if any) | |
Write-Host @timeStampParams | |
} | |
# ===================================================== | |
# Separator Handling Section | |
# ===================================================== | |
# Prepare the separator text | |
$separator = " - " | |
# Append the separator to the log buffer | |
$script:logBuffer += $separator | |
# Output the separator | |
$separatorParams = @{ | |
'Object' = $separator # Separator text | |
'NoNewline' = $true # Keep the cursor on the same line | |
} | |
# If a foreground color for the separator is provided, include it | |
if ($PSBoundParameters.ContainsKey('SeparatorColor') -and $SeparatorColor -and $SeparatorColor -ne 'Default') | |
{ | |
$separatorParams['ForegroundColor'] = $SeparatorColor | |
} | |
# Output the separator with the specified color (if any) | |
Write-Host @separatorParams | |
} | |
# ===================================================== | |
# Message Output Handling Section | |
# ===================================================== | |
# Determine whether to handle the -Text or -MessageSegments parameter | |
if ($PSBoundParameters.ContainsKey('Text') -and $null -ne $Text) | |
{ | |
# Append the text to the log buffer | |
$script:logBuffer += $Text | |
if ($ForegroundColor -eq 'Rainbow') | |
{ | |
# Define the rainbow color sequence | |
$rainbowColors = @('Red', 'DarkYellow', 'Yellow', 'Green', 'Cyan', 'DarkMagenta', 'Magenta') | |
# Iterate through each character and apply a color | |
foreach ($char in $Text.ToCharArray()) | |
{ | |
# Get a unique color index | |
$colorIndex = Get-UniqueColorIndex -Min 0 -Max 7 | |
$currentColor = $rainbowColors[$colorIndex % $rainbowColors.Count] | |
# Prepare parameters for Write-Host for each character | |
$charParams = @{ | |
'Object' = $char | |
'NoNewline' = $true | |
'ForegroundColor' = $currentColor | |
} | |
# Include BackgroundColor only if it's specified | |
if ($PSBoundParameters.ContainsKey('BackgroundColor') -and $BackgroundColor -and $BackgroundColor -ne 'Default') | |
{ | |
$charParams['BackgroundColor'] = $BackgroundColor | |
} | |
# Output the character with the specified color | |
Write-Host @charParams | |
} | |
} | |
else | |
{ | |
# Prepare a hashtable to hold parameters for Write-Host | |
$writeHostParams = @{ | |
'Object' = $Text # The text message to display | |
'NoNewline' = $true # Keep the cursor on the same line | |
} | |
# If a foreground color is specified for the text, include it | |
if ($PSBoundParameters.ContainsKey('ForegroundColor') -and $ForegroundColor -and $ForegroundColor -ne 'Default') | |
{ | |
$writeHostParams['ForegroundColor'] = $ForegroundColor | |
} | |
# If a background color is specified for the text, include it | |
if ($PSBoundParameters.ContainsKey('BackgroundColor') -and $BackgroundColor -and $BackgroundColor -ne 'Default') | |
{ | |
$writeHostParams['BackgroundColor'] = $BackgroundColor | |
} | |
# Output the text using Write-Host with the specified colors (if any) | |
Write-Host @writeHostParams | |
} | |
} | |
elseif ($PSBoundParameters.ContainsKey('MessageSegments') -and $null -ne $MessageSegments) | |
{ | |
foreach ($segment in $MessageSegments) | |
{ | |
# Append the segment text to the log buffer | |
$script:logBuffer += $segment.Text | |
if ($segment.ForegroundColor -eq 'Rainbow') | |
{ | |
# Define the rainbow color sequence | |
$rainbowColors = @('Red', 'DarkYellow', 'Yellow', 'Green', 'Cyan', 'DarkMagenta', 'Magenta') | |
# Iterate through each character and apply a color | |
foreach ($char in $segment.Text.ToCharArray()) | |
{ | |
# Get a unique color index | |
$colorIndex = Get-UniqueColorIndex -Min 0 -Max 7 | |
$currentColor = $rainbowColors[$colorIndex % $rainbowColors.Count] | |
# Prepare parameters for Write-Host for each character | |
$charParams = @{ | |
'Object' = $char | |
'NoNewline' = $true | |
'ForegroundColor' = $currentColor | |
} | |
# Include BackgroundColor only if it's specified | |
if ($segment.BackgroundColor -and $segment.BackgroundColor -ne 'Default') | |
{ | |
$charParams['BackgroundColor'] = $segment.BackgroundColor | |
} | |
# Output the character with the specified color | |
Write-Host @charParams | |
} | |
} | |
else | |
{ | |
# Prepare a hashtable to hold parameters for Write-Host for each segment | |
$writeHostParams = @{ | |
'Object' = $segment.Text # The text for this segment | |
'NoNewline' = $true # Keep the cursor on the same line | |
} | |
# If a foreground color is specified for this segment, include it | |
if ($segment.ForegroundColor -and $segment.ForegroundColor -ne 'Default') | |
{ | |
$writeHostParams['ForegroundColor'] = $segment.ForegroundColor | |
} | |
# If a background color is specified for this segment, include it | |
if ($segment.BackgroundColor -and $segment.BackgroundColor -ne 'Default') | |
{ | |
$writeHostParams['BackgroundColor'] = $segment.BackgroundColor | |
} | |
# Output the segment text using Write-Host with the specified colors (if any) | |
Write-Host @writeHostParams | |
} | |
} | |
} | |
else | |
{ | |
# If neither -Text nor -MessageSegments is provided, output a warning | |
$warningMessage = "Error: Please provide either -Text or -MessageSegments" | |
# Append the warning message to the log buffer | |
$script:logBuffer += $warningMessage | |
# Output the warning to the console | |
Write-Warning $warningMessage | |
} | |
# ===================================================== | |
# Newline Handling and Logging Section | |
# ===================================================== | |
# Add a newline after the message unless NoNewLine is specified | |
if (-not $NoNewLine) | |
{ | |
# Output a newline to the console | |
Write-Host "" | |
# Write the accumulated log buffer to the log file | |
try | |
{ | |
# Append the log buffer to the log file | |
Add-Content -Path $logFilePath -Value $script:logBuffer | |
} | |
catch | |
{ | |
# Output a warning if writing to the log file fails | |
Write-Warning "Failed to write to log file: $_" | |
} | |
# Clear the log buffer | |
$script:logBuffer = "" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment