当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 周五乐趣:Out-ConditionalColor

作者:精品下载站 日期:2024-12-14 07:39:48 浏览:16 分类:玩电脑

周五乐趣:Out-ConditionalColor


上周,我发布了一篇 Friday Fun 文章,介绍了解析 Invoke-Webrequest 的结果并以颜色显示匹配的字符串,以便使我感兴趣的书名脱颖而出。但我想得越多,我意识到我应该更进一步。 Write-Host 的问题在于它不会向管道写入任何内容,这就是我们通常不赞成使用它的原因。虽然能够使用颜色来突出显示某些东西是非常酷的。我想要颜色和流水线输出。这是我的结果。

#requires -version 3.0

Function Out-ConditionalColor {
<#
.Synopsis
Display colorized pipelined output.
.Description
This command is designed to take pipeline input and display it in a colorized
format, based on a set of conditions. Unlike Write-Host which doesn't write to
the pipeline, this command will write to the pipeline. You can get colorized 
data and save the output to a variable at the same time, although you'll need
to use the common OutVariable parameter (see examples).

The default behavior is to use a hash table with a property name and color. 
The color must be one of the standard console colors used with Write-Host.

$c = @{Stopped='Red';Running='Green'}

You can then pipe an expression to this command, specifying a property name and
the hash table. If the property matches the key name, the output for that object
will be colored using the corresponding hash table value.

get-service -diplayname windows* | out-conditionalcolor $c status 

Or you can do more complex processing with an ordered hash table constructed 
using this format:

[ordered]@{ <comparison scriptblock> = <color>}

The comparison scriptblock can use $PSitem.

$h=[ordered]@{
{$psitem.ws -gt 200mb}='yellow'
{$psitem.vm -gt 500mb}='red'
{$psitem.cpu -gt 300}='cyan'
}

When doing a complex comparison you must use an [ordered] hashtable as each key 
will be processed in order using an If/ElseIf statement.

This command should be the last part of any pipelined expression. If you pipe
to anything else, such as Sort-Object, you will lose your color formatting. Do
any other sorting or filtering before piping to this command.

This command requires PowerShell 3.0 and works best in the PowerShell console.
.Parameter Conditions
Use a simple hashtable for basic processing or an ordered hash table for complex.
.Parameter Property
When using a simple hash table, specify the property to compare using the -eq
operator. If you don't specify a property you will be prompted.
.Example
PS C:\> get-service -displayname windows* | out-conditionalcolor -conditions @{Stopped='Red'} -property Status

Get all services where the displayname starts with windows and display stopped services in red.
.Example
PS C:\> get-service -displayname windows* | out-conditionalcolor @{Stopped='Red'} status -ov winstop

Repeat the previous example, but save the output to the variable winstop. When
you look at $Winstop you'll see the services, but they won't be colored. This 
example uses the parameters positionally.
.Example
PS C:\> get-eventlog system -newest 50 | out-conditionalcolor @{error='red';warning='yellow'}
Enter a property name: entrytype

Get the newest 50 entries from the System event log. Display errors in red and warnings in yellow.
If you don't specify a property you will be prompted.
.Example
PS C:\> $c =[ordered]@{{$psitem.length -ge 1mb}='red';{$psitem.length -ge 500KB}='yellow';{$psitem.length -ge 100KB}='cyan'}
PS C:\> dir c:\scripts\*.doc,c:\scripts\*.pdf,c:\scripts\*.xml | Select Name,LastWriteTime,Length | out-conditionalcolor $c

The first command creates an ordered hashtable based on the Length property. 
The second command uses it to et certain file types in the scripts folder and 
display the selected properties in color depending on the file size.
.Notes
Last Updated: 9/17/2013
Version     : 0.9

Learn more about PowerShell:
Essential PowerShell Learning Resources

  ****************************************************************
  * DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED *
  * THOROUGHLY IN A LAB ENVIRONMENT. USE AT YOUR OWN RISK.  IF   *
  * YOU DO NOT UNDERSTAND WHAT THIS SCRIPT DOES OR HOW IT WORKS, *
  * DO NOT USE IT OUTSIDE OF A SECURE, TEST SETTING.             *
  ****************************************************************

.Link
Friday Fun: Out-ConditionalColor
.Link
About_Hash_Tables
#>

[cmdletbinding()]
Param(
[Parameter(Position=0,Mandatory=$True,HelpMessage="Enter an ordered hashtable of conditional properties and colors.")]
[ValidateScript({ 
$_ -IS [System.Collections.Specialized.OrderedDictionary] -OR ($_ -IS [hashtable])})]
[psobject]$Conditions,
[Parameter(Position=1,HelpMessage="Enter a property name.")]
[string]$Property,
[Parameter(Position=2,Mandatory=$True,ValueFromPipeline=$True)]
[PSObject[]]$Inputobject

)

Begin {
    Write-Verbose "Starting $($MyInvocation.MyCommand)"
    #save original color
    $saved = $Host.UI.RawUI.ForegroundColor
    Write-Verbose "Original foreground color is $saved"

    #validate colors
    $allowed = [enum]::GetNames([system.consolecolor])
    $bad = $Conditions.Values | where {$allowed -notcontains $_}
    if ($bad) {
        Write-Warning "You are using one or more invalid colors: $($bad -join ',')"
        Break
    }    
   
    if ($Conditions -is [System.Collections.Specialized.OrderedDictionary]) {
        $Complex = $True
        #we'll need this later in the Process script block
        #if doing complex processing
        Write-Verbose "Getting hash table enumerator and names"
        $compare = $conditions.GetEnumerator().name
        Write-Verbose $($compare | out-string)
        #build an If/ElseIf construct on the fly
#the Here strings must be left justified
$If=@"
 if ($($compare[0])) {
  `$host.ui.RawUI.ForegroundColor = '$($conditions.item($($compare[0])))'
 }
"@

        #now add the remaining comparisons as ElseIf
        for ($i=1;$i -lt $conditions.count;$i++) {
         $If+="elseif ($($compare[$i])) { 
         `$host.ui.RawUI.ForegroundColor = '$($conditions.item($($compare[$i])))'
         }
         "
        } #for

#add the final else
$if+=@"
Else { 
`$host.ui.RawUI.ForegroundColor = `$saved 
}
"@

        Write-Verbose "Complex comparison:"
        Write-Verbose $If
    } #if complex parameter set
    Else {
        #validate a property was specified
        if (-NOT $Property) {
            [string]$property = Read-Host "Enter a property name"
            if (-Not $property) { 
                Write-Verbose "Blank property so quitting"
                Break
            }
        }
        Write-Verbose "Conditional property is $Property"
    } 

} #Begin

Process {

    If ($Complex) {
        #Use complex processing
        Invoke-Expression $if        
  } #end complex
  else {
        #get property value as a string
        $value = $Inputobject.$Property.ToString()
        Write-Debug "Testing property value $value"
        if ($Conditions.containsKey($value)) {
         Write-Debug "Property match"
         $host.ui.RawUI.ForegroundColor= $Conditions.item($value)
        }
        else {
         #use orginal color
         Write-Debug "No matches found"
         $host.ui.RawUI.ForegroundColor= $saved
        }        
  } #simple

    #write the object to the pipeline
    Write-Debug "Write the object to the pipeline"
    $_
} #Process

End {
    Write-Verbose "Restoring original foreground color"
    #set color back
    $Host.UI.RawUI.ForegroundColor=$saved
} #end

} #close function

#create an optional alias
Set-Alias -Name occ -Value Out-ConditionalColor

此功能仅在 PowerShell 控制台中真正起作用。它旨在接受任何 PowerShell 输入。该函数还采用参数来帮助它以指定的颜色写入匹配的对象。使用该函数的简单方法是指定一个属性和一个哈希表。哈希表的键是您要在输入中匹配的值,键是您要使用的颜色。该函数在每个对象进入时对其进行处理,如果属性与值匹配,它将控制台的前景色设置为指定值。

$value = $Inputobject.$Property.ToString()
        Write-Debug "Testing property value $value"
        if ($Conditions.containsKey($value)) {
         Write-Debug "Property match"
         $host.ui.RawUI.ForegroundColor= $Conditions.item($value)
        }

如果不匹配,则前景色基本上保持不变。这意味着我可以运行这样的命令:

get-process | sort WS -descending | Out-ConditionalColor @{chrome='yellow'} -Property Name

并得到这样的结果:

[玩转系统] 周五乐趣:Out-ConditionalColor

每当进程名称等于“chrome”时,我都会将该对象显示为黄色。您还可以有多个条目。

get-eventlog system -newest 50 | out-conditionalcolor @{error='red';warning='yellow'}

[玩转系统] 周五乐趣:Out-ConditionalColor

$h=[ordered]@{
{$psitem.ws -gt 200mb}='yellow'
{$psitem.vm -gt 500mb}='red'
{$psitem.cpu -gt 300}='cyan'
}

这有点棘手。哈希表键是您要监视的对象属性和一些运算符比较的脚本块。该值是您要用于匹配的控制台颜色。使用 $psitem 表示管道中的当前对象。有序哈希表的原因是因为键是以 If/ElseIf 方式处理的,因此请确保以正确的顺序获取内容。

该函数分解哈希表并在 Begin 脚本块中构建 If/ElseIf 结构的此处字符串。

    if ($Conditions -is [System.Collections.Specialized.OrderedDictionary]) {
        $Complex = $True
        #we'll need this later in the Process script block
        #if doing complex processing
        Write-Verbose "Getting hash table enumerator and names"
        $compare = $conditions.GetEnumerator().name
        Write-Verbose $($compare | out-string)
        #build an If/ElseIf construct on the fly
#the Here strings must be left justified
$If=@"
 if ($($compare[0])) {
  `$host.ui.RawUI.ForegroundColor = '$($conditions.item($($compare[0])))'
 }
"@

        #now add the remaining comparisons as ElseIf
        for ($i=1;$i -lt $conditions.count;$i++) {
         $If+="elseif ($($compare[$i])) { 
         `$host.ui.RawUI.ForegroundColor = '$($conditions.item($($compare[$i])))'
         }
         "
        } #for

#add the final else
$if+=@"
Else { 
`$host.ui.RawUI.ForegroundColor = `$saved 
}
"@

        Write-Verbose "Complex comparison:"
        Write-Verbose $If
    } #if complex parameter set

这里的字符串包含设置主机前景色的命令。然后在 Process 脚本块中我使用 Invoke-Expression 来执行它。

   If ($Complex) {
        #Use complex processing
        Invoke-Expression $if
  } #end complex

但现在我可以做到这一点。

get-process | out-conditionalcolor -Conditions $h

[玩转系统] 周五乐趣:Out-ConditionalColor

get-process | out-conditionalcolor -Conditions $h -OutVariable p

$P 不会被着色(除非我再次通过该函数运行它),但我仍然有数据。

有一些限制。与任何 Out cmdlet 一样,这必须是管道表达式中的最后一个命令。从技术上讲,您可以在我的函数之后进行排序或过滤,但它会失去条件着色。与其他 Out cmdlet 不同,您无法将任何格式化数据通过管道传送给它。

该函数的重点是提供一种向 PowerShell 数据添加一些可视化引用的方法。

[玩转系统] 周五乐趣:Out-ConditionalColor

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯