Search notes:

Powershell module: console

Functions

get-ansiEscapedText Create text with ANSI escape sequences.
get-textInConsoleWarningColor etc.
write-textInConsoleWarningColor etc Writes text that is colored with get-textInConsoleWarningColor (etc.) to the console. Compare with $host.ui.writeError methods.
get-consoleLineText Gets a line from the console-buffer as a string.
move-cursor… etc. Move the cursor on the console
set-consolePaletteColor Modifies the color of an entry in the console palette colors.
set-consoleFontSize Change width and height of the font characters
set-consoleFontName Change the console face name (for example Courier New or Consolas)
get-consoleFont Gets font attributes as returned by GetCurrentConsoleFontEx
set-consoleSize Adjust the size (width and height) of the console. The change seems to be persistent across sessions. This function is inspired by Set-ConsoleSize.ps1 of ss64.com.
get-paletteIndexOfConsoleColor Gets the index of the color palette in the conhost.exe properties dialog from an entry of the System.ConsoleColor enum.

Source code

console.psm1

set-strictMode -version latest

function get-ansiEscapedText {

   param (
      [parameter(
        mandatory                   = $true,
        valueFromRemainingArguments = $true
      )]
      [object[]]                      $objs
   )

   $ret = ''
   foreach ($obj in $objs) {

     if ($obj -is [SGR]) {
        $ret += "$([char]27)[$($obj.value__)m"
     }
     else {
        $ret += $obj
     }

   }

   return $ret

}

function get-paletteIndexOfConsoleColor {
   param (
     [System.ConsoleColor] $color
   )

   if ($color -eq [System.ConsoleColor]::black      ) { return  0}
   if ($color -eq [System.ConsoleColor]::darkBlue   ) { return  1}
   if ($color -eq [System.ConsoleColor]::darkGreen  ) { return  2}
   if ($color -eq [System.ConsoleColor]::darkCyan   ) { return  3}
   if ($color -eq [System.ConsoleColor]::darkRed    ) { return  4}
   if ($color -eq [System.ConsoleColor]::darkMagenta) { return  5}
   if ($color -eq [System.ConsoleColor]::darkYellow ) { return  6}
   if ($color -eq [System.ConsoleColor]::gray       ) { return  7}

   if ($color -eq [System.ConsoleColor]::darkGray   ) { return  8}
   if ($color -eq [System.ConsoleColor]::blue       ) { return  9}
   if ($color -eq [System.ConsoleColor]::green      ) { return 10}
   if ($color -eq [System.ConsoleColor]::cyan       ) { return 11}
   if ($color -eq [System.ConsoleColor]::red        ) { return 12}
   if ($color -eq [System.ConsoleColor]::magenta    ) { return 13}
   if ($color -eq [System.ConsoleColor]::yellow     ) { return 14}
   if ($color -eq [System.ConsoleColor]::white      ) { return 15}
}

function set-cursorPosition {
   param(
      [uint16] $x,
      [uint16] $y
   )

   write-host -noNewLine "$([char]27)[$x;${y}H"
}

function set-consoleSize {
 #
 # Inspired and copied from https://ss64.com/ps/syntax-consolesize.html
 #

 [cmdletBinding()]
  param(
     [int] $reqWidth,
     [int] $reqHeight
  )

  $console    = $host.ui.rawui
  $conBuffer  = $console.BufferSize
  $conSize    = $console.WindowSize

  $height     = [Math]::Min($host.UI.RawUI.MaxPhysicalWindowSize.Height, $reqHeight)
  $width      = [Math]::Min($host.UI.RawUI.MaxPhysicalWindowSize.Width , $reqWidth )

  $currWidth  = $ConSize.Width
  $currHeight = $ConSize.height

  $currWidth  = [Math]::Min($conBuffer.Width , $width )
  $currHeight = [Math]::Min($conBuffer.Height, $height)

  $host.UI.RawUI.WindowSize = new-object System.Management.Automation.Host.Size($currWidth, $currHeight)
  $host.UI.RawUI.BufferSize = new-object System.Management.Automation.Host.Size($Width, $conBuffer.height)
  $host.UI.RawUI.WindowSize = new-object System.Management.Automation.Host.Size($Width, $height)

}

function move-cursor {

   param(
      [uint16] $n,
      [char]   $c
   )

   write-host -noNewLine "$([char]27)[$n$c"

}

function move-cursorUp {
   param( [uint16] $n = 1)
   move-cursor $n A
}

function move-cursorDown {
   param( [uint16] $n = 1)
   move-cursor $n B
}

function move-cursorRight {
   param( [uint16] $n = 1)
   move-cursor $n F           # F apparently stands for forward
}

function move-cursorLeft {
   param( [uint16] $n = 1)
   move-cursor $n B           # F apparently stands for backward
}

function move-cursorLine {
   param( [uint16] $n)
   move-cursor $n d
}

function move-cursorColumn {
   param( [uint16] $n)
   move-cursor $n G
}

function move-cursorNextLine {
   param( [uint16] $n)
   move-cursor $n E
}

function move-cursorPreviousLine {
   param( [uint16] $n)
   move-cursor $n F
}

function save-cursorPosition {
   write-host -noNewLine "$([char]27)[s"
}

function restore-cursorPosition {
   write-host -noNewLine "$([char]27)[u"
}

function set-consolePaletteColor {

   param (
      [byte] $paletteIndex,
      [byte] $r,
      [byte] $g,
      [byte] $b
   )

   $index = switch ($paletteIndex) {
      0 {  0 }
      1 {  4 }
      2 {  2 }
      3 {  6 }
      4 {  1 }
      5 {  5 }
      6 {  3 }
      7 {  7 }
      8 {  8 }
      9 { 12 }
     10 { 10 }
     11 { 14 }
     12 {  9 }
     13 { 13 }
     14 { 11 }
     15 { 15 }
   }

   write-host -noNewLine ("$([char]27)]4;{0};rgb:{1:X2}/{2:X2}/{3:X2}$([char]7)" -f $index, $r, $g, $b)
}

function get-ansiForConsoleColor {
    param (
      [parameter(mandatory=$true)]
       [System.ConsoleColor]           $consoleColor,
      [parameter(mandatory=$false)]
       [bool]                          $is_bg = $false
    )

    [byte] $color = $consoleColor.value__

    if ($color -gt 7) {
       $color = $color - 8
       $dark  = $true
    }
    else {
       $dark  = $false
    }

    if     ( $color -eq 0 ) { $code = 0 }
    elseif ( $color -eq 1 ) { $code = 4 }
    elseif ( $color -eq 2 ) { $code = 2 }
    elseif ( $color -eq 3 ) { $code = 6 }
    elseif ( $color -eq 4 ) { $code = 1 }
    elseif ( $color -eq 5 ) { $code = 5 }
    elseif ( $color -eq 6 ) { $code = 3 }
    elseif ( $color -eq 7 ) { $code = 7 } # gray, white...

    $ret = "$([char] 27)["

    if ($dark) { if ($is_bg) { $ret += '3' } else { $ret +=  '9'}}
    else       { if ($is_bg) { $ret += '4' } else { $ret += '10'}}

    $ret += $code
    $ret += 'm'

    return $ret
}

function get-textInConsoleXColor {
   param (
      [parameter(mandatory=$true)]
      [System.ConsoleColor]           $bg,
      [parameter(mandatory=$true)]
      [System.ConsoleColor]           $fg,
      [parameter(mandatory=$true)]
      [string]                        $text
   )

   $ret += ( get-ansiForConsoleColor  $bg $true )
   $ret += ( get-ansiForConsoleColor  $fg $false)

   $ret += $text

   $ret += "$([char] 27)[0m"

   return $ret

}

function get-textInConsoleWarningColor {
   param (
      [parameter(mandatory=$true)]
      [string]                     $text
   )

   return get-textInConsoleXColor $host.PrivateData.WarningBackgroundColor $host.PrivateData.WarningForegroundColor $text
}

function write-textInConsoleWarningColor {
   param (
      [parameter(mandatory=$true)]
      [string]                     $text
   )

   write-host (get-textInConsoleWarningColor $text)
}

function get-textInConsoleErrorColor {
   param (
      [parameter(mandatory=$true)]
      [string]                     $text
   )
   return get-textInConsoleXColor $host.PrivateData.ErrorBackgroundColor $host.PrivateData.ErrorForegroundColor $text
}

function write-textInConsoleErrorColor {
   param (
      [parameter(mandatory=$true)]
      [string]                     $text
   )

   write-host (get-textInConsoleErrorColor $text)
}

function get-consoleLineText {

   param (
      [parameter(mandatory=$false)]
      [int]                         $line  = -1,
      [switch]                      $noTrimEnd
   )

   if ($line -lt 0) {
      $line = $host.ui.rawui.CursorPosition.Y + $line-1
   }

   $region = new-object System.Management.Automation.Host.Rectangle `
          0                                   ,$line,               `
         ($host.ui.rawui.BufferSize.Width  -1),$line

   $cells = $host.ui.rawui.GetBufferContents($region)

   $ret= ''
   foreach ($cell in $cells) {
      $ret += $cell.Character
   }

   if (-not $noTrimEnd) {
      $ret = $ret.TrimEnd()
   }

   return $ret
}

function get-consoleFont {
   [Win32API.Console]::GetFont()
}

function set-consoleFontSize {
   param (
    # [int16] $w,  # V.8: The width does not seem to have any influence
      [int16] $h
   )
   [int16] $w = 0
   [Win32API.Console]::SetSize($w, $h)
}

function set-consoleFontName {
   param (
      [string] $name
   )
   [Win32API.Console]::SetName($name)
}

$src = get-content -raw "$psScriptRoot\console.cs"
add-type -typeDef $src
Github repository ps-modules-console, path: /console.psm1

console.psd1

@{
   RootModule         = 'console'
   ModuleVersion      = '0.9'

   RequiredAssemblies = @()

   RequiredModules    = @()

   FunctionsToExport  = @(
     'get-ansiEscapedText',
     'set-cursorPosition',
     'move-cursorUp', 'move-cursorDown', 'move-cursorLeft', 'move-cursorRight',
     'move-cursorNextLine', 'move-cursorPreviousLine',
     'move-cursorLine', 'move-cursorColumn',
     'save-cursorPosition', 'restore-cursorPosition',
     'get-paletteIndexOfConsoleColor',
     'set-consolePaletteColor',
     'set-consoleSize',
     'get-textInConsoleWarningColor', 'write-textInConsoleWarningColor'
     'get-textInConsoleErrorColor'  , 'write-textInConsoleErrorColor',
     'get-consoleLineText'
     'get-consoleFont',
     'set-consoleFontSize',
     'set-consoleFontName'
   )

   AliasesToExport   = @()

   ScriptsToProcess  = @(
    # 'console.ps1'       # V0.9: apparently not used, why has it ever gotten into the psd?
   )
}
Github repository ps-modules-console, path: /console.psd1

console.cs

using System;
using System.Runtime.InteropServices;

namespace Win32API {
public static class Console {

   [StructLayout(LayoutKind.Sequential)]
    public struct COORD {

        public short X;
        public short Y;

        public COORD(short x, short y) {
           X = x;
           Y = y;
        }
    }

   [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct CONSOLE_FONT_INFOEX
    {
        public uint  cbSize;
        public uint  n;
        public COORD size;

        public int   family; // The four low-order bits of 'family' specify information about the pitch and the technology:
                             //     1 = TMPF_FIXED_PITCH, 2 = TMPF_VECTOR, 4 = TMPF_TRUETYPE, 8 = TMPF_DEVICE.
                             // The four high-order bits specifies the fonts family:
                             //     80 = FF_DECORATIVE, 0 = FF_DONTCARE, 48 = FF_MODERN, 16 = FF_ROMAN, 64 = FF_SCRIPT, 32 = FF_SWISS
                             //     I assume(!) this value is always 48.
                             //    (In fact, it seems that family is is always 54 = TMPF_VECTOR + TMPF_TRUETYPE + FF_MODERN)
        public int   weight;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string name;
    }


    
   [DllImport("kernel32.dll", SetLastError = true)] 
    public static extern IntPtr GetStdHandle( 
        int nStdHandle 
    ); 
    

   [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    extern static bool GetCurrentConsoleFontEx(
       IntPtr hConsoleOutput,
       bool   bMaximumWindow,
       ref    CONSOLE_FONT_INFOEX lpConsoleCurrentFont
    );

   [DllImport("kernel32.dll", SetLastError = true)]
    static extern Int32 SetCurrentConsoleFontEx(
        IntPtr ConsoleOutput,
        bool   MaximumWindow,
        ref    CONSOLE_FONT_INFOEX lpConsoleCurrentFont
     );

    public static CONSOLE_FONT_INFOEX GetFont() {
     CONSOLE_FONT_INFOEX ret = new CONSOLE_FONT_INFOEX();

     ret.cbSize = (uint) Marshal.SizeOf(ret);
     if (GetCurrentConsoleFontEx(GetStdHandle(-11), false, ref ret)) {
        return ret;
     }

     throw new Exception("something went wrong with GetCurrentConsoleFontEx");
  }

  public static void SetFont(CONSOLE_FONT_INFOEX font) {

    if (SetCurrentConsoleFontEx(GetStdHandle(-11), false, ref font ) == 0) {
       throw new Exception("something went wrong with SetCurrentConsoleFontEx");

    }

  }

  public static void SetSize(short w, short h) {
     CONSOLE_FONT_INFOEX font = GetFont();
     font.size.X = w;
     font.size.Y = h;
     SetFont(font);
  }

  public static void SetName(string name) {
     CONSOLE_FONT_INFOEX font = GetFont();
     font.name = name;
     SetFont(font);

  }


}
}
Github repository ps-modules-console, path: /console.cs

History

V0.3 get-consoleLineText
V0.4 get-ansiEscapedText, cursor movements, set-consolePaletteColor, get-paletteIndexOfConsoleColor
V0.5 Add set-consoleSize
V0.7 Add set-consoleFontSize, set-consoleFontName and get-consoleFont (2022-08-10: added some comments in the source code about the family member of CONSOLE_FONT_INFOEX)
V0.8 Removed parameter $w from set-consoleFont because the width didn't seem to have any influence.
V0.9 Removed unnecessary reference to console.ps1 in ScriptsToProcess.

See also

René's simple PowerShell modules

Index