如何(正确)对 PowerShell 5.1 默认输出进行着色

问题描述 投票:0回答:1

关于对 PowerShell 输出进行着色已经存在几个问题,例如:

这对我来说在最新的 PowerShell 7 版本中工作得很好,但我想让我的模块向下兼容 Windows PowerShell 5.1,如果相关的彩色字符串被截断(例如以表格格式),则颜色不会重置。

最小的、可重复的示例:

$Esc = [Char]0x1b
[PSCustomObject]@{
    Path = 'Person.Address'
    Node = "$Esc[36m@{City='New York';..;PostalCode='10021-3100'}$Esc[39m"
    Test = 'Optional'
    Issue = "$Esc[91m[X] The actual item contains unapproved child items: PostalCode. Expected an item with optional child items listed in @{State=@{..};..;City=@{..}}.$Esc[39m"
}

enter image description here

(注意第二行的

Path
属性的颜色和提示颜色都变成了red,如果
Issue
属性适合屏幕的话不会发生什么)

PowerShell 5.1 是否有一种方法可以确保始终重置字符串的 ANSI 颜色(即使它被截断)?

powershell output powershell-5.1 colorize
1个回答
0
投票

如果您同意不对输入内联进行颜色编码,您可以使用 format.ps1xml 文件定义自定义视图。 请参阅此处如何创建您自己的视图。

例如,对于我的一个模块,我定义了一个如下所示的视图:

<?xml version="1.0" encoding="utf-8"?>
<Configuration>
    <ViewDefinitions>
        <View>
            <Name>Kra.TimeTrackerTime</Name>
            <ViewSelectedBy>
                <TypeName>TimeTrackerTime</TypeName>
            </ViewSelectedBy>
            <GroupBy>
                <!--<PropertyName>Date</PropertyName>-->
                <ScriptBlock>"$($_.Date.DayOfWeek), $($_.Date.ToString('dd.MM.yyyy'))"</ScriptBlock>
                <Label>Group</Label>
            </GroupBy>
            <TableControl>
                <TableHeaders>
                    <TableColumnHeader>
                        <Label>TaskName</Label>
                        <Width>20</Width>
                        <Alignment>Left</Alignment>
                    </TableColumnHeader>
                    <TableColumnHeader>
                        <Label>BookingCode</Label>
                        <Width>14</Width>
                        <Alignment>Left</Alignment>
                    </TableColumnHeader>
                    <TableColumnHeader>
                        <Label>Status</Label>
                        <Width>16</Width>
                        <Alignment>Left</Alignment>
                    </TableColumnHeader>
                    <TableColumnHeader>
                        <Label>Date</Label>
                        <Width>12</Width>
                        <Alignment>Left</Alignment>
                    </TableColumnHeader>
                    <TableColumnHeader>
                        <Label>StartTime</Label>
                        <Width>5</Width>
                        <Alignment>Right</Alignment>
                    </TableColumnHeader>
                    <TableColumnHeader>
                        <Label>EndTime</Label>
                        <Width>7</Width>
                        <Alignment>Right</Alignment>
                    </TableColumnHeader>
                    <TableColumnHeader>
                        <Label>Duration</Label>
                        <Width>8</Width>
                        <Alignment>Right</Alignment>
                    </TableColumnHeader>
                    <TableColumnHeader>
                        <Label>Comment</Label>
                        <Width>68</Width>
                        <Alignment>Left</Alignment>
                    </TableColumnHeader>
                </TableHeaders>
                <TableRowEntries>
                    <TableRowEntry>
                        <Wrap />
                        <TableColumnItems>
                            <TableColumnItem>
                                <ScriptBlock>
                                    $Value = $_.TaskName
                                    $Esc = [char]27
                                    if($_.IsRunning) {
                                        $Color = '38;2;66;224;22'
                                        $Format = $true
                                    }
                                    if($_.IsArchived) {
                                        $Color = '38;2;120;120;120'
                                        $Format = $true
                                    }
                                    if($_.IsBreakTime) {
                                        $Color = '38;2;80;130;255'
                                        $Format = $true
                                    }
                                    if($Format) {
                                        "$Esc[$($Color)m$($Value)$Esc[0m"
                                    }
                                    else {
                                        $Value
                                    }
                                </ScriptBlock>
                            </TableColumnItem>
                            <TableColumnItem>
                                <ScriptBlock>
                                    $Value = $_.BookingCode
                                    $Esc = [char]27
                                    if($_.IsBreakTime) {
                                        $Color = '38;2;80;130;255'
                                        $Format = $true
                                    }
                                    if($_.IsRunning) {
                                        $Color = '38;2;66;224;22'
                                        $Format = $true
                                    }
                                    if($_.IsArchived) {
                                        $Color = '38;2;120;120;120'
                                        $Format = $true
                                    }
                                    if($Format) {
                                        "$Esc[$($Color)m$($Value)$Esc[0m"}
                                    else {
                                        $Value
                                    }
                                </ScriptBlock>
                            </TableColumnItem>
                            <TableColumnItem>
                                <ScriptBlock>
                                    $Value = $_.Status -join ";`n"
                                    $Esc = [char]27
                                    if($_.IsBreakTime) {
                                        $Color = '38;2;80;130;255'
                                        $Format = $true
                                    }
                                    if($_.IsRunning) {
                                        $Color = '38;2;66;224;22'
                                        $Format = $true
                                    }
                                    if($_.IsArchived) {
                                        $Color = '38;2;120;120;120'
                                        $Format = $true
                                    }
                                    if('Pikett' -in $_.Status) {
                                        $Color = '38;2;255;150;60'
                                        $Format = $true
                                    }
                                    if($Format) {
                                        "$Esc[$($Color)m$($Value)$Esc[0m"}
                                    else {
                                        $Value
                                    }
                                </ScriptBlock>
                            </TableColumnItem>
                            <TableColumnItem>
                                <ScriptBlock>
                                    $Value = $_.Date.ToString('dd.MM.yyyy')
                                    $Esc = [char]27
                                    if($_.IsBreakTime) {
                                        $Color = '38;2;80;130;255'
                                        $Format = $true
                                    }
                                    if($_.IsRunning) {
                                        $Color = '38;2;66;224;22'
                                        $Format = $true
                                    }
                                    if($_.IsArchived) {
                                        $Color = '38;2;120;120;120'
                                        $Format = $true
                                    }
                                    if($Format) {
                                        "$Esc[$($Color)m$($Value)$Esc[0m"
                                    }
                                    else {
                                        $Value
                                    }
                                </ScriptBlock>
                            </TableColumnItem>
                            <TableColumnItem>
                                <ScriptBlock>
                                    $Value = $_.StartTime.ToString('HH:mm')
                                    $Esc = [char]27
                                    if($_.IsBreakTime) {
                                        $Color = '38;2;80;130;255'
                                        $Format = $true
                                    }
                                    if($_.IsRunning) {
                                        $Color = '38;2;66;224;22'
                                        $Format = $true
                                    }
                                    if($_.IsArchived) {
                                        $Color = '38;2;120;120;120'
                                        $Format = $true
                                    }
                                    if($Format) {
                                        "$Esc[$($Color)m$($Value)$Esc[0m"
                                    }
                                    else {
                                        $Value
                                    }
                                </ScriptBlock>
                            </TableColumnItem>
                            <TableColumnItem>
                                <ScriptBlock>
                                    $Value = $_.EndTime.ToString('HH:mm')
                                    $Esc = [char]27
                                    if($_.IsBreakTime) {
                                        $Color = '38;2;80;130;255'
                                        $Format = $true
                                    }
                                    if($_.IsRunning) {
                                        $Color = '38;2;66;224;22'
                                        $Format = $true
                                    }
                                    if($_.IsArchived) {
                                        $Color = '38;2;120;120;120'
                                        $Format = $true
                                    }
                                    if($Format) {
                                        "$Esc[$($Color)m$($Value)$Esc[0m"
                                    }
                                    else {
                                        $Value
                                    }
                                </ScriptBlock>
                            </TableColumnItem>
                            <TableColumnItem>
                                <ScriptBlock>
                                    $Value = $_.Duration.ToString('hh\hmm')
                                    $Esc = [char]27
                                    if($_.IsBreakTime) {
                                        $Color = '38;2;80;130;255'
                                        $Format = $true
                                    }
                                    if($_.IsArchived) {
                                        $Color = '38;2;120;120;120'
                                        $Format = $true
                                    }
                                    if($_.IsRunning) {
                                        $Color = '38;2;66;224;22'
                                        $Format = $true
                                    }
                                    if($Format) {
                                        "$Esc[$($Color)m$($Value)$Esc[0m"
                                    }
                                    else {
                                        $Value
                                    }
                                </ScriptBlock>
                            </TableColumnItem>
                            <TableColumnItem>
                                <ScriptBlock>
                                    $Value = $_.Comment
                                    $Esc = [char]27
                                    if($_.IsBreakTime) {
                                        $Color = '38;2;80;130;255'
                                        $Format = $true
                                    }
                                    if($_.IsRunning) {
                                        $Color = '38;2;66;224;22'
                                        $Format = $true
                                    }
                                    if($_.IsArchived) {
                                        $Color = '38;2;120;120;120'
                                        $Format = $true
                                    }
                                    if($Format) {
                                        "$Esc[$($Color)m$($Value)$Esc[0m"
                                    }
                                    else {
                                        $Value
                                    }
                                </ScriptBlock>
                            </TableColumnItem>
                        </TableColumnItems>
                    </TableRowEntry>
                </TableRowEntries>
            </TableControl>
        </View>
    </ViewDefinitions>
</Configuration>

注意“ViewSelectedBy”标签。它有一个指定的 TypeName。在您的代码中,您必须将该 TypeName 添加到您想要在此视图中显示的任何对象,如下所示:

#create the object and store it in a variable
$Obj = [PsCustomObject]@{
    TaskName    = $_.TaskName
    BookingCode = $Task.BookingCode
    Status      = $Status
    IsBreakTime = $Task.IsBreakTime
    Date        = $ObjDate
    StartTime   = $_.StartTime
    EndTime     = $_.EndTime
    Duration    = $Duration
    Comment     = $_.Comment
    IsRunning   = $null -eq $_.EndTime
    IsArchived  = $_.IsArchived
}

#the object has a list of TypeNames
#insert the TypeName specified in the view
$Obj.PsTypeNames.Insert(0,'TimeTrackerTime')
Write-Output $Obj

只要您按照链接文章中的指定加载视图(您可以将其放入 PowerShell 配置文件脚本中),任何具有指定 TypeName 的对象都将自动在控制台中显示该视图。

如果您的代码位于 PowerShell 模块中,您可以将 format.ps1xml 文件添加到模块目录中,并在“FormatsToProcess”下的模块清单中指定路径。

© www.soinside.com 2019 - 2024. All rights reserved.