有人向我提出了一个问题,如果我希望命令按顺序操作,建议使用Write-Output而不是Write-Host(因为Write-Host不会将输出放在管道上,而其他命令会这样做,这意味着Write-Host输出可能发生在管道上的其他命令之前或之后,从而导致输出非常混乱):command execution ordering inside a PowerShell scriptblock
遵循这个建议,我使用Write-Output做了一个简单的函数来模仿Write-Host的颜色语法。对于排序,这很好用,所以命令的输出现在是连续的,但是Write-Output的颜色输出现在很糟糕,所以如果我使用任何BackgroundColor,结果以非常丑陋的方式喷在屏幕上。Write-Host在彩色输出方面紧密可靠,并且没有“t出血到其他部分的控制台,所以使用写输出与颜色使一些真正丑陋/笨重的控制台输出。
我需要在离开这个函数之前以某种方式重置$host.ui吗?或者有人能建议一种方法来修改这个函数,使颜色保持在需要它们的区域,而不会渗到其他控制台区域吗?
function Write-Color ($text, $ForegroundColor, $BackgroundColor) {
$defaultFore = $host.ui.RawUI.ForegroundColor
$defaultBack = $host.ui.RawUI.BackgroundColor
if ($ForegroundColor -ne $null) { $host.ui.RawUI.ForegroundColor = $ForegroundColor }
if ($BackgroundColor -ne $null) { $host.ui.RawUI.BackgroundColor = $BackgroundColor }
Write-Output $text
$host.ui.RawUI.ForegroundColor = $defaultFore
$host.ui.RawUI.BackgroundColor = $defaultBack
}
例如:
Write-Color "The dog sat on the couch" -ForegroundColor Red -BackgroundColor White
1条答案
按热度按时间nqwrtyyt1#
Write-Host
* 是 * 生成(可能是彩色的)for-display 输出的正确工具-而不是通过PowerShell的 *success输出流 *、cmdlet调用和表达式(可选地通过显式Write-Output
调用,但很少需要)输出 * 数据 。This answer解释了如果您 * 混合 *
Write-Host
和success-stream输出,在PowerShell v5+中,打印到控制台的内容可能会出现 * 乱序。这是隐式应用的“表格”格式设置的“副作用”,它在打印输出之前收集一些数据,以便确定合适的列宽。这种情况只发生在(a)没有预定义格式数据,(b)具有4个或更少属性的输出类型(因为具有更多属性的类型默认为“列表”格式设置)。
在GitHub issue #4594中讨论了有问题的行为;虽然仍有希望找到解决办法,但很长一段时间没有任何活动。
**对于此问题,没有好的解决方案(从PowerShell 7.0开始):
有两个次优的变通方法:
... | Out-Host
。Select-Object
调用的命令发送到Out-Host
,以便正确显示在屏幕上的两个Write-Host
调用 * 之间 *:*缺点:使用
Out-Host
意味着您将无法捕获或重定向命令输出,因为它会直接发送到 * 主机 *(显示器)。此外,(a)了解哪些命令会触发问题,(b)记得对每个命令应用解决方法也很麻烦。Write-Host
调用替换为向成功输出流 * 发送具有嵌入的VT (Virtual Terminal) escape sequences(用于着色) 的字符串。**缺点:(彩色的)字符串成为代码的 * 数据输出 * 的一部分,因此在捕获/重定向输出时 * 被包括在内 *。
... | Where-Object { -not ($_ -is [string] -and $_ -match '\e') }
嵌入VT转义序列允许您选择性地为字符串的 * 部分 * 着色。
用
Write-Host
实现同样的效果需要用-NoNewline
进行 * 多次 * 调用。第三方cmdlet(模块)
Write-ColoredOutput
模拟Write-Host
的语法,并使用[console]
类型的属性打开和关闭着色,同时将字符串发送到 success output stream。这对于用给定的颜色编写 * 整个 * 字符串非常有效,但是您不能将不同颜色的部分拼凑在 * 一行 * 上,因为每个单独写入success输出流的字符串总是在其自己的行 * 上打印 *。
如果您想要一个方便的 Package 器来将VT序列直接嵌入到字符串中,您可以修改
Write-HostColored
函数from this answer,方法是将幕后发生的Write-Host
调用替换为VT序列。