powershell是否允许您检测输出是否被定向到屏幕,与管道传输到变量/文件?

时间:2014-11-12 09:59:56

标签: powershell pipeline

我知道这种感觉就像在管道上的“错误方向”上移动状态一样,但在某些情况下这可能很方便。

此代码段是否可行?

if (Directed-To-Screen) {
    Write-Host "Error!" -ForegroundColor Red 
} else {
    Write-Output "Error!"
}    

如果当前代码/脚本通过管道传输到变量或文件等,Directed-To-Screen将返回$ false(我知道[Console]::ForegroundColor \ $host.UI.RawUI.ForegroundColor可用于着色 - 在某些游戏机中输出。)

如果要将格式化打印在屏幕上,实际上可以做很多工作来改进格式化,而实用程序函数的管道输出可能应该被构造成可以消耗单个字段。能够分辨他们可能非常有用。 (没有办法让PSObject覆盖其ToString格式,以便在打印到屏幕时看起来很漂亮,是吗?)

甚至可能无法检测它是否在屏幕上显示。任何人都可以确认吗?

1 个答案:

答案 0 :(得分:3)

我认为你是以错误的方式接近这个。您应该输出一个在终端上以红色显示但在写入文件时看起来像纯文本的对象,而不是使用Write-Host并强制使用红色前景色。

已经有一个对象可以做到这一点:任何类型为System.Management.Automation.ErrorRecord的对象如果到达管道的末尾都会显示为红色但可以写入文件。不幸的是,对于您的目的,它通常使用CategoryIdFullyQualifiedErrorId字段进行格式化,但如果错误对象是由本机命令创建的,则不会这样做。我们可以假装这样的行为:

function Write-RedText
{
    [CmdletBinding()]
    [OutputType([int])]
    Param
    (
        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true,
                   Position=0)]
        $Text
    )

    Begin
    {
    }
    Process
    {
       foreach ($s in $Text)
       {
           #Wr$o = (Write-Error $s -ErrorId NativeCommandErrorMessage -TargetObject $None) 2>&1
           $o = new-object -TypeName "System.Management.Automation.ErrorRecord" -ArgumentList ($s, "NativeCommandErrorMessage", [System.Management.Automation.ErrorCategory]::FromStdErr, "c")
           $o | Add-Member -NotePropertyName writeErrorStream -NotePropertyValue $True
          Write-Output $o
       }
    }
    End
    {
    }
}

现在你可以这样做:

Write-RedText "Error!"

如果它到达主机,它将显示为红色,但如果它最终存在于文件中,则显示为纯文本。

N.B。对象上的writeErrorStream属性实际上使其显示为红色,因此可以通过添加该属性使其他对象显示为红色。 e.g。

$out = ls
$out | Add-Member -NotePropertyName writeErrorStream -NotePropertyValue $True
$out

会在控制台上为您提供一个红色的目录列表,或者您希望将WriteWarningStream属性设置为橙色文本。

关于你的其余问题,我很确定无法确定输出结束的位置。最外层管道的末尾有一个隐式| Out-DefaultOut-Default格式化对象并将它们发送到控制台,但是没有办法判断任何对象是否到达最终命令,或者它们是否重新定义Out-Default以完成不同的操作。