Múltiples colores de primer plano en PowerShell en un comando

Quiero mostrar muchos colores de primer plano diferentes con una statement.

PS C:\> Write-Host "Red" -ForegroundColor Red Red 

Esta salida es roja.

 PS C:\> Write-Host "Blue" -ForegroundColor Blue Blue 

Esta salida es azul.

 PS C:\> Write-Host "Red", "Blue" -ForegroundColor Red, Blue Red Blue 

Este resultado es magenta, pero quiero que el color sea rojo para la palabra rojo y azul para la palabra azul a través del comando. ¿Cómo puedo hacer eso?

Editar (7 de mayo de 2018): actualicé Write-Color a 0.5 y lo publiqué como módulo. También el código ahora está publicado en github.

Cambios en 0.5:

  • color de fondo agregado
  • añadido alias T / B / C al código más corto
  • alias añadido a la función (se puede usar con “WC”)
  • correcciones a la publicación de módulos

Cambios en 0.4

  • arreglado pequeños problemas
  • publicado como módulo

Enlaces a recursos:

  • Repositorio GitHub
  • Problemas con los informes de GitHub
  • Módulo PowerShellGallery
  • Descripción del módulo y un punto de partida.

Gracias al módulo publicado puede usar fácilmente el código de la siguiente manera:

 Install-Module PSWriteColor Write-Color -Text "Some","Text" -Color Yellow,Red 

Ya no es necesario copiar / pegar el código. Disfrutar.

El código anterior está abajo. Se recomienda encarecidamente utilizar los enlaces de arriba para el código más nuevo:

Editar (9 de abril de 2018): actualicé Write-Color a v0.3 . No dude en obtenerlo en mi sitio donde estoy manteniendo Write-Color . Hay algunos pequeños cambios. Inluded – NoNewLine y – ShowTime option.

Editar (junio de 2017): actualizado con una nueva versión, agregado de registro al archivo para fines de registro

El método de Josh fue tan bueno que realmente fui y lo amplié un poco para mis necesidades. He escrito una publicación en un blog sobre cómo formatear PowerShell con Múltiples colores (con capturas de pantalla y todo, para toda la historia y el uso).

  function Write-Color([String[]]$Text, [ConsoleColor[]]$Color = "White", [int]$StartTab = 0, [int] $LinesBefore = 0,[int] $LinesAfter = 0, [string] $LogFile = "", $TimeFormat = "yyyy-MM-dd HH:mm:ss") { # version 0.2 # - added logging to file # version 0.1 # - first draft # # Notes: # - TimeFormat https://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx $DefaultColor = $Color[0] if ($LinesBefore -ne 0) { for ($i = 0; $i -lt $LinesBefore; $i++) { Write-Host "`n" -NoNewline } } # Add empty line before if ($StartTab -ne 0) { for ($i = 0; $i -lt $StartTab; $i++) { Write-Host "`t" -NoNewLine } } # Add TABS before text if ($Color.Count -ge $Text.Count) { for ($i = 0; $i -lt $Text.Length; $i++) { Write-Host $Text[$i] -ForegroundColor $Color[$i] -NoNewLine } } else { for ($i = 0; $i -lt $Color.Length ; $i++) { Write-Host $Text[$i] -ForegroundColor $Color[$i] -NoNewLine } for ($i = $Color.Length; $i -lt $Text.Length; $i++) { Write-Host $Text[$i] -ForegroundColor $DefaultColor -NoNewLine } } Write-Host if ($LinesAfter -ne 0) { for ($i = 0; $i -lt $LinesAfter; $i++) { Write-Host "`n" } } # Add empty line after if ($LogFile -ne "") { $TextToFile = "" for ($i = 0; $i -lt $Text.Length; $i++) { $TextToFile += $Text[$i] } Write-Output "[$([datetime]::Now.ToString($TimeFormat))]$TextToFile" | Out-File $LogFile -Encoding unicode -Append } } Write-Color -Text "Red ", "Green ", "Yellow " -Color Red,Green,Yellow Write-Color -Text "This is text in Green ", "followed by red ", "and then we have Magenta... ", "isn't it fun? ", "Here goes DarkCyan" -Color Green,Red,Magenta,White,DarkCyan Write-Color -Text "This is text in Green ", "followed by red ", "and then we have Magenta... ", "isn't it fun? ", "Here goes DarkCyan" -Color Green,Red,Magenta,White,DarkCyan -StartTab 3 -LinesBefore 1 -LinesAfter 1 Write-Color "1. ", "Option 1" -Color Yellow, Green Write-Color "2. ", "Option 2" -Color Yellow, Green Write-Color "3. ", "Option 3" -Color Yellow, Green Write-Color "4. ", "Option 4" -Color Yellow, Green Write-Color "9. ", "Press 9 to exit" -Color Yellow, Gray -LinesBefore 1 Write-Color -LinesBefore 2 -Text "This little ","message is ", "written to log ", "file as well." -Color Yellow, White, Green, Red, Red -LogFile "C:\testing.txt" -TimeFormat "yyyy-MM-dd HH:mm:ss" Write-Color -Text "This can get ","handy if ", "want to display things, and log actions to file ", "at the same time." -Color Yellow, White, Green, Red, Red -LogFile "C:\testing.txt" 

Cómo formatear PowerShell con múltiples colores

En realidad trae controles y funciones adicionales sobre el script de Josh.

Puede desplegar su propio comando Write-Color o algo que busque tokens en línea que cambien el color. Así es como las secuencias de escape de ANSI solían funcionar en los días de BBS.

Pero puedes lograr lo que quieres haciendo:

 Write-Host "Red " -f red -nonewline; Write-Host "Blue " -f blue; 

Aquí hay una pequeña función simple que hace lo que le pediste.

 function Write-Color([String[]]$Text, [ConsoleColor[]]$Color) { for ($i = 0; $i -lt $Text.Length; $i++) { Write-Host $Text[$i] -Foreground $Color[$i] -NoNewLine } Write-Host } Write-Color -Text Red,White,Blue -Color Red,White,Blue 

Esta función proporciona diferentes azúcares sintácticos:

 function color-Write { # DO NOT SPECIFY param(...) # we parse colors ourselves. $allColors = ("-Black", "-DarkBlue","-DarkGreen","-DarkCyan","-DarkRed","-DarkMagenta","-DarkYellow","-Gray", "-Darkgray","-Blue", "-Green", "-Cyan", "-Red", "-Magenta", "-Yellow", "-White") $foreground = (Get-Host).UI.RawUI.ForegroundColor # current foreground $color = $foreground [bool]$nonewline = $false $sofar = "" $total = "" foreach($arg in $args) { if ($arg -eq "-nonewline") { $nonewline = $true } elseif ($arg -eq "-foreground") { if ($sofar) { Write-Host $sofar -foreground $color -nonewline } $color = $foregrnd $sofar = "" } elseif ($allColors -contains $arg) { if ($sofar) { Write-Host $sofar -foreground $color -nonewline } $color = $arg.substring(1) $sofar = "" } else { $sofar += "$arg " $total += "$arg " } } # last bit done special if (!$nonewline) { Write-Host $sofar -foreground $color } elseif($sofar) { Write-Host $sofar -foreground $color -nonewline } } 

Ejemplos:

 color-Write This is normal text color-Write Normal -Red Red -White White -Blue Blue -ForeGround Normal 

Aquí hay una pequeña función que escribí para producir texto en color (en realidad es más pequeña, pero la reescribí para que sea más comprensible):

 function Write-Color() { Param ( [string] $text = $(Write-Error "You must specify some text"), [switch] $NoNewLine = $false ) $startColor = $host.UI.RawUI.ForegroundColor; $text.Split( [char]"{", [char]"}" ) | ForEach-Object { $i = 0; } { if ($i % 2 -eq 0) { Write-Host $_ -NoNewline; } else { if ($_ -in [enum]::GetNames("ConsoleColor")) { $host.UI.RawUI.ForegroundColor = ($_ -as [System.ConsoleColor]); } } $i++; } if (!$NoNewLine) { Write-Host; } $host.UI.RawUI.ForegroundColor = $startColor; } 

Es bastante simple de usar: simplemente use Write-Color "your text" y agregue algún nombre de color entre llaves donde desee que el texto se coloree.

Ejemplos:

 `Write-Color "Hello, {red}my dear {green}friend !"` will output 

Captura de pantalla de script

Puede colocarlo en su archivo $profile para usarlo en un simple mensaje de PowerShell, o simplemente agregarlo a algunos scripts.

Esto también funciona …

 Write-Host "Don't forget to " -ForegroundColor Yellow -NoNewline; Write-Host "CALL YOUR MOM " -ForegroundColor Red -NoNewline; Write-Host "every day!" -ForegroundColor Yellow 

Encuentre la función avanzada Write-HostColored continuación, que permite incrustar instrucciones de color en una cadena, tanto para el primer plano como para el color de fondo:

 Write-HostColored "I'm #green#green#, I'm #red#red#, and I'm #blue:white#blue on white#." 

Los rendimientos anteriores:

muestra de salida

Además de aceptar un color de primer plano y de fondo predeterminado con -ForegroundColor y -BackgroundColor , puede incrustar una o más especificaciones de color en la cadena para escribir, usando la siguiente syntax:

 #[:]## 

y deben ser valores [ConsoleColor] válidos, como green o white (caso no importa). Todo lo que sigue a la especificación de color hasta el siguiente # , o implícitamente hasta el final de la cadena, está escrito en ese color.


Write-HostColored fuente Write-HostColored (PSv2 +):

 <# .SYNOPSIS A wrapper around Write-Host that supports selective coloring of substrings via embedded coloring specifications. .DESCRIPTION In addition to accepting a default foreground and background color, you can embed one or more color specifications in the string to write, using the following syntax: #[:]##  and  must be valid [ConsoleColor] values, such as 'green' or 'white' (case does not matter). Everything following the color specification up to the next '#', or impliclitly to the end of the string, is written in that color. Note that nesting of color specifications is not supported. As a corollary, any token that immediately follows a color specification is treated as text to write, even if it happens to be a technically valid color spec too. This allows you to use, eg, 'The next word is #green#green#.', without fear of having the second '#green' be interpreted as a color specification as well. .PARAMETER ForegroundColor Specifies the default text color for all text portions for which no embedded foreground color is specified. .PARAMETER BackgroundColor Specifies the default background color for all text portions for which no embedded background color is specified. .PARAMETER NoNewline Output the specified string withpout a trailing newline. .NOTES While this function is convenient, it will be slow with many embedded colors, because, behind the scenes, Write-Host must be called for every colored span. .EXAMPLE Write-HostColored "#green#Green foreground.# Default colors. #blue:white#Blue on white." .EXAMPLE '#black#Black on white (by default).#Blue# Blue on white.' | Write-HostColored -BackgroundColor White #> function Write-HostColored() { [CmdletBinding()] param( [parameter(Position=0, ValueFromPipeline=$true)] [string[]] $Text , [switch] $NoNewline , [ConsoleColor] $BackgroundColor = $host.UI.RawUI.BackgroundColor , [ConsoleColor] $ForegroundColor = $host.UI.RawUI.ForegroundColor ) begin { # If text was given as a parameter value, it'll be an array. # Like Write-Host, we flatten the array into a single string # using simple string interpolation (which defaults to separating elements with a space, # which can be changed by setting $OFS). if ($Text -ne $null) { $Text = "$Text" } } process { if ($Text) { # Start with the foreground and background color specified via # -ForegroundColor / -BackgroundColor, or the current defaults. $curFgColor = $ForegroundColor $curBgColor = $BackgroundColor # Split message into tokens by '#'. # A token between to '#' instances is either the name of a color or text to write (in the color set by the previous token). $tokens = $Text.split("#") # Iterate over tokens. $prevWasColorSpec = $false foreach($token in $tokens) { if (-not $prevWasColorSpec -and $token -match '^([az]*)(:([az]+))?$') { # a potential color spec. # If a token is a color spec, set the color for the next token to write. # Color spec can be a foreground color only (eg, 'green'), or a foreground-background color pair (eg, 'green:white'), or just a background color (eg, ':white') try { $curFgColor = [ConsoleColor] $matches[1] $prevWasColorSpec = $true } catch {} if ($matches[3]) { try { $curBgColor = [ConsoleColor] $matches[3] $prevWasColorSpec = $true } catch {} } if ($prevWasColorSpec) { continue } } $prevWasColorSpec = $false if ($token) { # A text token: write with (with no trailing line break). # !! In the ISE - as opposed to a regular PowerShell console window, # !! $host.UI.RawUI.ForegroundColor and $host.UI.RawUI.ForegroundColor inexcplicably # !! report value -1, which causes an error when passed to Write-Host. # !! Thus, we only specify the -ForegroundColor and -BackgroundColor parameters # !! for values other than -1. # !! Similarly, PowerShell Core terminal windows on *Unix* report -1 too. $argsHash = @{} if ([int] $curFgColor -ne -1) { $argsHash += @{ 'ForegroundColor' = $curFgColor } } if ([int] $curBgColor -ne -1) { $argsHash += @{ 'BackgroundColor' = $curBgColor } } Write-Host -NoNewline @argsHash $token } # Revert to default colors. $curFgColor = $ForegroundColor $curBgColor = $BackgroundColor } } # Terminate with a newline, unless suppressed if (-not $NoNewLine) { write-host } } } 

Este código está disponible con una cantidad diferente de argumentos: Texto, ForeGroundColor y BackGroundColor.

Cada lista de colores se usa con una implementación de rotación:

 function Write-Color([String[]]$Text, [ConsoleColor[]]$ForeGroundColor, [ConsoleColor[]]$BackGroundColor) { for ($i = 0; $i -lt $Text.Length; $i++) { $Color = @{} if ($ForeGroundColor -and $BackGroundColor){ $Color = @{ ForegroundColor = $ForeGroundColor[$i%($ForeGroundColor.count)] BackgroundColor = $BackGroundColor[$i%($BackGroundColor.count)] } } elseif ($ForeGroundColor) { $Color = @{ ForegroundColor = $ForeGroundColor[$i%($ForeGroundColor.count)] } } elseif ($BackGroundColor) { $Color = @{ BackgroundColor = $BackGroundColor[$i%($BackGroundColor.count)] } } Write-Host $Text[$i] @color -NoNewLine } Write-Host } 

Uso de registro:

 Write-Color "Check color list...".PadRight(50), '[', ' OK ', ']' -fore cyan, White, green, white Write-Color "Red Check is good...".PadRight(50), '[' ,' ERROR! ', ']' -fore cyan, White, red, white Write-Color "Write-Color is cool !".PadRight(50), '[', ' WARN ', ']' -fore cyan, White, Yellow, white 

Ingrese la descripción de la imagen aquí

Uso de la lista (solo 2 backGroundColor y 4 foreGroundColor):

 Write-Color (@(100..115) | %{" -> $_ : ".PadRight(30) + "`n"}) -ForeGroundColor cyan, yellow, magenta, red -BackGroundColor gray, black 

Ingrese la descripción de la imagen aquí

Standard Write-Host

 Write-Host (@(100..115) | %{" -> $_ : ".PadRight(30) + "`n"}) -BackgroundColor gray 

Ingrese la descripción de la imagen aquí

Estaba intentando ejecutar esto en un cuadro de Windows Server 2012R2 bajo ISE y la función de Jesse Chisholm estaba fallando porque por alguna razón (Get-Host) .UI.RawUII.ForegroundColor era -1. Para detener esto y simplificar la función, poco lo modifiqué de la siguiente manera:

 function Write-ColorText { # DO NOT SPECIFY param(...) # we parse colors ourselves. $allColors = ("-Black", "-DarkBlue","-DarkGreen","-DarkCyan","-DarkRed","-DarkMagenta","-DarkYellow","-Gray", "-Darkgray","-Blue", "-Green", "-Cyan", "-Red", "-Magenta", "-Yellow", "-White", "-Foreground") $color = "Foreground" $nonewline = $false foreach($arg in $args) { if ($arg -eq "-nonewline") { $nonewline = $true } elseif ($allColors -contains $arg) { $color = $arg.substring(1) } else { if ($color -eq "Foreground") { Write-Host $arg -nonewline } else { Write-Host $arg -foreground $color -nonewline } } } Write-Host -nonewline:$nonewline } 

Sé que esta es una publicación anterior, pero espero que esto sea útil para alguien y gracias Jesse por darme esta maravillosa función.

Leve modificación a esta … Tomé la versión 2, eliminé el registro (porque no lo quiero), y luego agregué un parámetro booleano, similar a -NoNewLine para Write-Host. Intenté específicamente agregar la capacidad de cambiar los colores y solicitar la entrada del usuario en la misma línea para poder resaltar la respuesta predeterminada si el usuario no ingresa nada.

Me doy cuenta de que esto estaba disponible en Write-HostColored (en una respuesta anterior) … pero a veces solo quieres un código más simple …

 function Write-Color([String[]]$Text, [ConsoleColor[]]$Color = "White", [int]$StartTab = 0, [int] $LinesBefore = 0,[int] $LinesAfter = 0, [bool] $NewLine = $True) { # Notes: # - TimeFormat https://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx # # Example: Write-Color -Text "Red ", "Green ", "Yellow " -Color Red,Green,Yellow -NewLine $False # $DefaultColor = $Color[0] if ($LinesBefore -ne 0) { for ($i = 0; $i -lt $LinesBefore; $i++) { Write-Host "`n" -NoNewline } } # Add empty line before if ($StartTab -ne 0) { for ($i = 0; $i -lt $StartTab; $i++) { Write-Host "`t" -NoNewLine } } # Add TABS before text if ($Color.Count -ge $Text.Count) { for ($i = 0; $i -lt $Text.Length; $i++) { Write-Host $Text[$i] -ForegroundColor $Color[$i] -NoNewLine } } else { for ($i = 0; $i -lt $Color.Length ; $i++) { Write-Host $Text[$i] -ForegroundColor $Color[$i] -NoNewLine } for ($i = $Color.Length; $i -lt $Text.Length; $i++) { Write-Host $Text[$i] -ForegroundColor $DefaultColor -NoNewLine } } if ($NewLine -eq $False) { Write-Host -NoNewLine } else { Write-Host } if ($LinesAfter -ne 0) { for ($i = 0; $i -lt $LinesAfter; $i++) { Write-Host "`n" } } # Add empty line after } # END FUNCTION Write-Color 

Muestra de lo que estaba tratando de lograr:

 Write-Color -Text "Is this correct? ","[y]","/n" -Color White, Magenta, White -NewLine $False ; Read-Host " " 

Si usted está en mi situación, he encontrado una manera simple de Microsoft Doc para configurar el modo de consola. Así que aquí hay una manera fácil de iniciar y finalizar el soporte de la consola ansi de 256 colores tanto en cmd como en powershell:

 // https://docs.microsoft.com/en-us/windows/console/setconsolemode #include  #include  struct console_data { HANDLE hstdin; DWORD mode; DWORD start() { hstdin = GetStdHandle(STD_OUTPUT_HANDLE); GetConsoleMode(hstdin, &mode); if (!SetConsoleMode(hstdin, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) { DWORD E = GetLastError(); std::cout << " Error #" << E << "in:" __FUNCTION__ "\n"; return GetLastError(); } std::cout << "\033[1;14mReady.\e[0m\n"; return 0; } void end() { SetConsoleMode(hstdin, mode); } ~console_data() { end(); } //... }RTConsole; //... int main() { //... RTConsole.start(); std::cout << "\033[38;5;192m Should be 'Orange'\n"; RTConsole.end(); return 0; } 

https://docs.microsoft.com/en-us/windows/console/setconsolemode

Nota: No encontré cómo obtener compatibilidad con 256 colores en la extensión posShell del Código VS.