it-swarm.com.ru

Несколько цветов переднего плана в PowerShell в одной команде

Я хочу вывести много разных цветов переднего плана с одним утверждением.

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

Этот вывод красный.

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

Этот вывод синий.

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

Это вывод Magenta, но я хочу, чтобы красный цвет для Word был красным, а синий для Word - синим с помощью одной команды. Как я могу это сделать?

50
Mark Tomlin

Изменить (7 мая 2018 года): я обновил Write-Color до 0.5 и опубликовал его в виде модуля. Также код теперь опубликован на github.

Изменения в 0.5:

  • добавлен цвет фона
  • добавлены псевдонимы T/B/C к более короткому коду 
  • добавлен псевдоним для функции (может использоваться с «WC»)
  • исправления в публикации модулей

Изменения в 0.4

  • исправлены небольшие проблемы
  • опубликовано в виде модуля

Ссылки на ресурсы:

Благодаря опубликованному модулю вы можете легко использовать код, как показано ниже:

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

Больше нет необходимости копировать/вставлять код. Наслаждаться.

Старый код ниже. Настоятельно рекомендуется использовать ссылки выше для новейшего кода:

Изменить (9 апреля 2018 года): я обновил Write-Color до v0.3. Не стесняйтесь получить его на моем сайте, где я поддерживаю Write-Color . Есть несколько небольших изменений. Включена опция -NoNewLine и -ShowTime

Редактировать (июнь 2017 г.): обновлено новой версией, добавлено ведение журнала в файл для целей ведения журнала

Метод Джоша был настолько хорош, что я даже немного расширил его для своих нужд. Я написал сообщение в блоге Как отформатировать PowerShell с несколькими цветами об этом (со скриншотами и всем - для всей истории и использования). 

    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

Это на самом деле приносит дополнительные проверки и функции над сценарием Джоша.

30
MadBoy

Вы можете запустить свою собственную команду Write-Color или что-то, что ищет встроенные токены, которые меняют цвет. Вот как экранирующие последовательности ANSI использовались, чтобы работать в дни BBS.

Но вы могли бы достичь того, что вы хотите, делая:

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

Вот простая маленькая функция, которая делает то, что вы просили.

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

Эта функция обеспечивает различный синтаксический сахар:

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

Примеры:

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

Вот небольшая функция, которую я написал для вывода цветного текста (на самом деле она меньше, но я переписала ее, чтобы она была более понятной):

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

Его довольно просто использовать: просто используйте Write-Color "your text" и добавьте название цвета в фигурных скобках, где вы хотите, чтобы текст был цветным.

Примеры:

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

Скриншот скрипта

Вы можете поместить его в свой файл $profile, чтобы использовать его в простой подсказке PowerShell, или просто добавить его в некоторые сценарии.

4
Raphaël Gomes

Это тоже работает ...

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

Небольшая модификация этого ... Я взял версию 2, удалил протоколирование (потому что оно мне не нужно), а затем добавил логический параметр, аналогичный -NoNewLine для Write-Host. Я специально пытался добавить возможность изменять цвета и Запрашивать ввод пользователя в одной строке, чтобы я мог выделить ответ по умолчанию, если пользователь ничего не вводит.

Я понимаю, что это было доступно в Write-HostColored (в предыдущем ответе) ... но иногда вам просто нужен более простой код ...

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

Пример того, что я пытался сделать:

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

Найдите расширенный function Write-HostColored ниже, который позволяет встраивать инструкции раскраски в строку, как для переднего плана, так и для фона:

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

Вышеуказанные выходы:

 sample output

В дополнение к принятию цвета переднего плана и фона по умолчанию с помощью -ForegroundColor и -BackgroundColor, Вы можете встроить одну или несколько спецификаций цвета в строку для записи, , Используя следующий синтаксис:

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

<fgcolor> и <bgcolor> должны быть действительными значениями [ConsoleColor], такими как green или white (регистр не имеет значения) . Все, что следует за спецификацией цвета до следующего # или неявно до конца строки, записывается в этом цвете ,.


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:
#<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

Этот код доступен с другим количеством аргументов: Text, ForeGroundColor и BackGroundColor.

Каждый список цветов используется с реализацией поворота:

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
}

Использование журнала:

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

Использование списка (всего 2 backGroundColor и 4 foreGroundColor):

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

 Enter image description here

Стандартный Write-Host

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

 Enter image description here

1
Alban

Я пытался запустить это на Windows Server 2012R2 на компьютере под управлением ISE, и функция Джесси Чишолма не работала, потому что по какой-то причине (Get-Host) .UI.RawUII.ForegroundColor был равен -1. Чтобы остановить это и упростить функцию, я немного изменил ее следующим образом:

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
}

Я знаю, что это старый пост, но надеюсь, что он кому-нибудь пригодится, и спасибо Джесси за то, что он дал мне эту замечательную функцию !!

0
pauby

Я нашел гораздо более простой вариант в https://blogs.technet.Microsoft.com/heyscriptingguy/2011/05/17/writing-output-with-powershell/

По сути, первая запись-Host включает опцию -NoNewLine. Это предотвращает формирование новой линии. Следующая запись-Хост будет добавлена ​​сразу после предыдущего текста. И каждый отдельный хост записи может иметь параметры -foregroundcolor. Это может повторяться для каждого изменения цвета, которое вам нужно.

Пример с одной строкой текста с тремя цветами:

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

Обратите внимание, что после текста в первом и втором write-Host есть пробел. PowerShell не объединяет и не объединяет текст, он просто не перемещает курсор на следующую строку.

0
Clifford

Вот упрощенный способ сделать это

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

Если вы находитесь в моей ситуации, я нашел простой путь Vanilla из документации Microsoft, чтобы установить режим консоли. Итак, вот простой способ начать и завершить поддержку консоли в 256 цветов в cmd и 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

Примечание: Я не нашел, как получить поддержку 256 цветов в расширении poswershell VS Code.

0
Bretzelus