web-dev-qa-db-fra.com

Plusieurs couleurs de premier plan dans PowerShell en une seule commande

Je souhaite générer de nombreuses couleurs de premier plan avec une seule déclaration.

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

Cette sortie est rouge.

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

Cette sortie est bleue.

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

Cette sortie est Magenta, mais je veux que la couleur soit rouge pour le mot rouge et bleu pour le mot bleu via la commande one. Comment puis je faire ça?

50
Mark Tomlin

Edit (7 mai 2018): J'ai mis à jour Write-Color à 0.5 et le publie sous forme de module. De plus, le code est maintenant publié sur github.

Changements en 0.5:

  • couleur d'arrière-plan ajoutée
  • ajout d'alias T/B/C à un code plus court 
  • ajout d'un alias pour fonctionner (peut être utilisé avec “WC”)
  • corrections à la publication de modules

Changements dans 0.4

  • correction de petits problèmes
  • publié en tant que module

Liens vers des ressources:

Grâce au module publié, vous pouvez facilement utiliser le code ci-dessous:

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

Il n'y a plus besoin de copier/coller du code. Prendre plaisir.

Ancien code est ci-dessous. Il est vivement conseillé d'utiliser les liens ci-dessus pour le code le plus récent:

Edit (9 avril 2018): J'ai mis à jour Write-Color à v0.3. N'hésitez pas à l'obtenir sur mon site sur lequel je maintiens Write-Color . Il y a peu de petits changements. Inluded -NoNewLine et -ShowTime

Edit (juin 2017): mise à jour avec la nouvelle version, ajout de la journalisation dans le fichier à des fins de journalisation

La méthode Josh était tellement géniale que je suis allée l’étendre un peu pour répondre à mes besoins. J'ai écrit un article de blog Comment formater PowerShell avec plusieurs couleurs à ce sujet (avec des captures d'écran et tout - pour toute l'histoire et l'utilisation) 

    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"

 How to format PowerShell with Multiple Colors

Il apporte en fait des vérifications et des fonctionnalités supplémentaires par rapport au script Josh.

30
MadBoy

Vous pouvez lancer votre propre commande Write-Color ou quelque chose qui recherche les jetons en ligne qui changent de couleur. C'est ainsi que les séquences d'échappement ANSI fonctionnaient dans les jours BBS.

Mais vous pouvez réaliser ce que vous voulez en faisant:

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

Voici une petite fonction simple qui fait ce que vous avez demandé.

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
48
Josh

Cette fonction fournit différents sucres syntaxiques:

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
    }
}

Exemples:

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

Voici une petite fonction que j'ai écrite pour produire du texte coloré (il est en fait plus petit, mais je l'ai récrit pour le rendre plus compréhensible):

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;
}

C'est assez simple à utiliser: utilisez simplement Write-Color "your text" et ajoutez un nom de couleur entre accolades où vous voulez que le texte soit coloré.

Exemples:

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

Capture d'écran du script

Vous pouvez le mettre dans votre fichier $profile pour l'utiliser dans une invite PowerShell simple, ou simplement l'ajouter à certains scripts.

4
Raphaël Gomes

Cela fonctionne aussi ...

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

Légère modification de celle-ci ... J'ai pris la version 2, supprimé la journalisation (parce que je ne le voulais pas), puis ajouté un paramètre booléen, similaire à -NoNewLine pour Write-Host. J'essayais spécifiquement d'ajouter la possibilité de changer les couleurs et de demander une entrée utilisateur sur la même ligne afin de pouvoir mettre en surbrillance la réponse par défaut si l'utilisateur ne saisissait rien.

Je me rends compte que cela était disponible dans Write-HostColored (dans une réponse précédente) ... mais parfois vous voulez juste du code plus 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

Exemple de ce que j'essayais d'accomplir:

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

Trouvez la function Write-HostColored avancée ci-dessous, qui permet d'incorporer des instructions de coloriage dans une chaîne, à la fois pour le premier plan et la couleur d'arrière-plan:

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

Les rendements ci-dessus:

 sample output

En plus d'accepter une couleur d'avant-plan et d'arrière-plan par défaut avec -ForegroundColor et -BackgroundColor, , Vous pouvez incorporer une ou plusieurs spécifications de couleur dans la chaîne à écrire, En utilisant la syntaxe suivante:

#<fgcolor>[:<bgcolor>]#<text>#

<fgcolor> et <bgcolor> doivent être des valeurs [ConsoleColor] valides, telles que green ou white (la casse importe peu) . Tout ce qui suit la spécification de couleur jusqu'au prochain # ou implicitement jusqu'à la fin de la chaîne est écrit dans cette couleur. .


Write-HostColored code source (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:
#<fgcolor>[:<bgcolor>]#<text>#

<fgcolor> and <bgcolor> 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, e.g., '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 '^([a-z]*)(:([a-z]+))?$') { # 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 (e.g., 'green'), or a foreground-background color pair (e.g., 'green:white'), or just a background color (e.g., ':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 }
    }
}
1
mklement0

Ce code est disponible avec un nombre d'arguments différent: Text, ForeGroundColor et BackGroundColor.

Chaque liste de couleurs est utilisée avec une implémentation de rotation:

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
}

Utilisation du journal:

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

 Enter image description here

Utilisation de la liste (seulement 2 backGroundColor et 4 foreGroundColor):

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

 Enter image description here

Écriture hôte standard

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

 Enter image description here

1
Alban

J'essayais de l'exécuter sur une machine Windows Server 2012R2 sous ISE et la fonction de Jesse Chisholm échouait car, pour une raison quelconque (Get-Host) .UI.RawUII.ForegroundColor était -1. Pour arrêter cela et simplifier la fonction, je l’ai modifiée comme suit:

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
}

Je sais que ceci est un ancien post mais j'espère que cela sera utile à quelqu'un et merci à Jesse de m'avoir donné cette merveilleuse fonction !!

0
pauby

J'ai trouvé une option beaucoup plus simple sur https://blogs.technet.Microsoft.com/heyscriptingguy/2011/05/17/writing-output-with-powershell/

Fondamentalement, le premier hôte en écriture inclut l'option -NoNewLine. Cela empêche la nouvelle ligne de se former. Le prochain hôte en écriture sera ajouté immédiatement après le texte précédent. Et chaque hôte d'écriture séparé peut avoir des options -foregroundcolor. Cela peut être répété pour chaque changement de couleur dont vous avez besoin.

Exemple avec une ligne de texte avec trois couleurs:

write-Host "Your text here " -ForeGroundColor Red -NoNewLine
write-Host "some other text here " -ForeGroundColor Yellow -NoNewLine
write-Host "And the last text here."

Notez qu'il y a un espace après le texte dans les premier et deuxième hôtes en écriture. PowerShell ne concatène pas ou ne combine pas le texte, il ne déplace simplement pas le curseur à la ligne suivante.

0
Clifford

Voici une façon simpliste de le faire

if ($help)
{

    Write-Host "     For the switch " -NoNewline; Write-Host " -userUniqueId" -ForegroundColor Green -NoNewline; Write-Host ", enter an email address or samaccountname (pin) so '-userUniqueId 123456' "
    Write-Host "";
    Write-Host "     For the switch " -NoNewline; Write-Host " -disableMFAForUser" -ForegroundColor Green -NoNewline; Write-Host ", enter an email address or samaccountname (pin) with the -userUniqueId and then '-disableMFAForUser $true' "
    Write-Host "";
    Write-Host "     For the switch " -NoNewline; Write-Host "-enableMFAForUser" -ForegroundColor Green -NoNewline; Write-Host ", enter an email address or samaccountname (pin) with the -userUniqueId and then '-enableMFAForUser $true' "
    Write-Host "";
    Write-Host "     For the switch " -NoNewline; Write-Host "-verifyAllMFAEnabled" -ForegroundColor Green -NoNewline; Write-Host ", enter '-verifyAllMFAEnabled $true' "
    Write-Host "";
    Write-Host "     For the switch " -NoNewline; Write-Host " -verifyAllMFADisabledSpecificUser" -ForegroundColor Green -NoNewline; Write-Host ", enter an email address or samaccountname (pin) and then '-verifyAllMFADisabledSpecificUser $true' "
    Write-Host "";

    return;
}
0
Bbb

Si vous êtes dans ma situation, j'ai trouvé un moyen simple de Microsoft docs de définir le mode console. Voici donc un moyen facile de démarrer et de terminer la prise en charge de la console Ansi en 256 couleurs dans cmd et powershell:

// https://docs.Microsoft.com/en-us/windows/console/setconsolemode
#include <Windows.h>
#include <iostream>
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

Note: Je n'ai pas trouvé comment obtenir le support de 256 couleurs dans l'extension poswershell de VS Code.

0
Bretzelus