Public/console/Write-ColorOutput.ps1

function Write-ColorOutput {
  # .SYNOPSIS
  # Colored Write-Output
  # .DESCRIPTION
  # Produce colored output on the console without compromising the expected Output object type.
  # Useful when showing info in the console host while avoiding producing strings in the output Objects.
  # .EXAMPLE
  # C:\> ls -Force | Write-ColorOutput -f 'Green'
  # .EXAMPLE
  # Help about_foreach | Write-ColorOutput -f Green
  # .INPUTS
  # Parsable Object
  # .OUTPUTS
  # Default output object type.
  # .NOTES
  # #BUG: Some commands don't work! Example:
  # $list = foreach ($file in Get-ChildItem) { if ($file.length -gt 100) { $($file | Select-Object Name, @{l = 'Size'; e = { $_.Length } }) } }
  # $list | Write-ColorOutput -F Green -b Black
  # #BUG This command works:
  # Help about_foreach | Write-ColorOutput -f Green -b Black # but,
  [alias('Cecho')]
  [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'Name')]
  param(
    [Parameter(Mandatory = $false, ParameterSetName = 'Name')]
    [Alias('f')]
    [ArgumentCompleter({
        [OutputType([System.Management.Automation.CompletionResult])]
        param(
          [string]$CommandName,
          [string]$ParameterName,
          [string]$WordToComplete,
          [System.Management.Automation.Language.CommandAst]$CommandAst,
          [System.Collections.IDictionary]$FakeBoundParameters
        )
        $CompletionResults = [System.Collections.Generic.List[System.Management.Automation.CompletionResult]]::new()
        [Enum]::GetValues([ConsoleColor]) | Where-Object { $_.ToString() -like "$wordToComplete*" } | ForEach-Object {
          $CompletionResults.Add([System.Management.Automation.CompletionResult]::new($_, $_, "ParameterValue", $_))
        }
        return $CompletionResults
      })]
    [string]$ForegroundColor,
    [Parameter(Mandatory = $false, ParameterSetName = 'Name')]
    [Alias('b')]
    [ArgumentCompleter({
        [OutputType([System.Management.Automation.CompletionResult])]
        param(
          [string]$CommandName,
          [string]$ParameterName,
          [string]$WordToComplete,
          [System.Management.Automation.Language.CommandAst]$CommandAst,
          [System.Collections.IDictionary]$FakeBoundParameters
        )
        $CompletionResults = [System.Collections.Generic.List[System.Management.Automation.CompletionResult]]::new()
        [Enum]::GetValues([ConsoleColor]) | Where-Object { $_.ToString() -like "$wordToComplete*" } | ForEach-Object {
          $CompletionResults.Add([System.Management.Automation.CompletionResult]::new($_, $_, "ParameterValue", $_))
        }
        return $CompletionResults
      })]
    [string]$BackgroundColor,
    # Object to write
    [parameter(Mandatory = $false, ParameterSetName = 'Name', valueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $true)]
    [Alias('i')]
    [Object[]]$InputObject
  )

  begin {
    $fc = $ExecutionContext.Host.UI.RawUI.ForegroundColor
    $bc = $ExecutionContext.Host.UI.RawUI.BackgroundColor
  }
  process {
    $ConsoleColors = $([ConsoleColor].GetMembers() | Where-Object { $_.MemberType -eq 'Field' -and $null -eq $_.FieldHandle }).Name
    try {
      if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('ForegroundColor')) {
        if ($ForegroundColor -in $ConsoleColors) {
          if ($PSCmdlet.ShouldProcess("Host.UI", "Set ForegroundColor")) { $ExecutionContext.Host.UI.RawUI.ForegroundColor = $ForegroundColor }
        } else {
          $PSCmdlet.WriteWarning("$fxn Used Invalid ForegroundColor Parameter.")
        }
      }
      if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('BackgroundColor')) {
        if ($BackgroundColor -in $ConsoleColors) {
          if ($PSCmdlet.ShouldProcess("Host.UI", "Set BackgroundColor")) { $ExecutionContext.Host.UI.RawUI.BackgroundColor = $BackgroundColor }
        } else {
          $PSCmdlet.WriteWarning("$fxn Used Invalid BackgroundColor Parameter.")
        }
      }
      $(if ($PSBoundParameters.Keys.Contains("InputObject")) { $InputObject } else { $input }) | ForEach-Object { Write-Output $_ }
    } catch [System.Management.Automation.SetValueInvocationException] {
      $ErrRecord = New-ErrorRecord -Exception [System.Management.Automation.SetValueInvocationException]::New('Invalid Color Name used. Take a walk, come back, then try using Tab Completion.')
      $PSCmdlet.WriteError($ErrRecord)
    } catch {
      $PSCmdlet.WriteError([System.Management.Automation.ErrorRecord]$_)
    } finally {
      $ExecutionContext.Host.UI.RawUI.ForegroundColor = $fc
      $ExecutionContext.Host.UI.RawUI.BackgroundColor = $bc
    }
  }
}