我有一个powershell脚本,通过 write-output 提供一些状态输出。我故意不使用 write-host ,因为输出可能被捕获并写入这样的日志文件:
./myscript.ps1 | out-file log.txt
但是如果输出没有被重定向,那么在控制台上输出彩色输出会很好,因为脚本会产生许多不同的状态消息。我知道 write-host 可以使用彩色输出,但状态消息应该是可管理的。
任何想法如何解决这个问题?
答案 0 :(得分:10)
我尝试了这个额外的功能,它基本上可以正常工作:
function Write-ColorOutput($ForegroundColor)
{
# save the current color
$fc = $host.UI.RawUI.ForegroundColor
# set the new color
$host.UI.RawUI.ForegroundColor = $ForegroundColor
# output
if ($args) {
Write-Output $args
}
else {
$input | Write-Output
}
# restore the original color
$host.UI.RawUI.ForegroundColor = $fc
}
# test
Write-ColorOutput red (ls)
Write-ColorOutput green (ls)
ls | Write-ColorOutput yellow
这个特殊测试的结果虽然有点滑稽:我们确实得到了红色,绿色和黄色的线条但是表格标题是红色的,即函数第一次调用的颜色。
答案 1 :(得分:7)
将管道上的结果与控制台中的状态消息分开。
例如,在脚本中使用这样的函数:
function write-status( $status ){
$status | write-host -fore green -back red; #send a status msg to the console
$status | write-output; #send a status object down the pipe
}
我还建议你使用以下cmdlet之一而不是write-host来输出脚本中的状态消息:
这些状态消息的外观将根据使用的cmdlet而有所不同。此外,用户可以使用$(warning | error | verbose | debug)首选项变量禁用特定级别的状态,或使用 - (warning | error | verbose | debug)变量常用cmdlet参数捕获特定状态消息。
答案 2 :(得分:1)
我遇到了同样的问题,所以我分享了我认为非常有效的解决方案:
Write-ColorOutput "Hello" Green Black -NoNewLine
Write-ColorOutput " World" Red
这是使用它的Cmdlet
function Write-ColorOutput
{
[CmdletBinding()]
Param(
[Parameter(Mandatory=$False,Position=1,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)][Object] $Object,
[Parameter(Mandatory=$False,Position=2,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)][ConsoleColor] $ForegroundColor,
[Parameter(Mandatory=$False,Position=3,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)][ConsoleColor] $BackgroundColor,
[Switch]$NoNewline
)
# Save previous colors
$previousForegroundColor = $host.UI.RawUI.ForegroundColor
$previousBackgroundColor = $host.UI.RawUI.BackgroundColor
# Set BackgroundColor if available
if($BackgroundColor -ne $null)
{
$host.UI.RawUI.BackgroundColor = $BackgroundColor
}
# Set $ForegroundColor if available
if($ForegroundColor -ne $null)
{
$host.UI.RawUI.ForegroundColor = $ForegroundColor
}
# Always write (if we want just a NewLine)
if($Object -eq $null)
{
$Object = ""
}
if($NoNewline)
{
[Console]::Write($Object)
}
else
{
Write-Output $Object
}
# Restore previous colors
$host.UI.RawUI.ForegroundColor = $previousForegroundColor
$host.UI.RawUI.BackgroundColor = $previousBackgroundColor
}
答案 3 :(得分:1)
这种方式:
function Green
{
process { Write-Host $_ -ForegroundColor Green }
}
function Red
{
process { Write-Host $_ -ForegroundColor Red }
}
Write-Output "this is a test" | Green
Write-Output "this is a test" | Red
答案 4 :(得分:0)
我知道这篇文章很古老,但对于那里的人来说这可能会派上用场。
我想改变颜色,接受的答案不是最佳解决方案。在我看来,以下代码是更好的解决方案,因为它利用了本机PowerShell功能:
修改强>
# Print User message using String Array $message
function PrintMessageToUser {
param(
[Parameter( `
Mandatory=$True, `
Valuefrompipeline = $true)]
[String]$message
)
begin {
$window_private_data = (Get-Host).PrivateData;
# saving the original colors
$saved_background_color = $window_private_data.VerboseBackgroundColor
$saved_foreground_color = $window_private_data.VerboseForegroundColor
# setting the new colors
$window_private_data.VerboseBackgroundColor = 'Black';
$window_private_data.VerboseForegroundColor = 'Red';
}
process {
foreach ($Message in $Message) {
# Write-Host Considered Harmful - see http://www.jsnover.com/blog/2013/12/07/write-host-considered-harmful/
# first way how to correctly write it
#Write-host $message;
Write-Verbose -Message $message -Verbose;
# second correct way how to write it
#$VerbosePreference = "Continue"
#Write-Verbose $Message;
}
}
end {
$window_private_data.VerboseBackgroundColor = $saved_background_color;
$window_private_data.VerboseForegroundColor = $saved_foreground_color;
}
} # end PrintMessageToUser
答案 5 :(得分:0)
我有同样的问题,我需要以交互方式用颜色记录屏幕输出,并以自动方式将该输出发送到文件。
我的解决方案是使用一个参数来指示输出类型('Screen' 或 'File'),然后函数可以决定如何渲染输出。
function Write-Color([String[]]$Text, [ConsoleColor[]]$Color, [ConsoleColor]$BackgroundColor = ([console]::BackgroundColor), $OutputType='Screen') {
switch ($OutputType) {
'Screen' {
for ($i = 0; $i -lt $Text.Length; $i++) {
Write-Host $Text[$i] -Foreground $Color[$i] -NoNewLine -BackgroundColor $BackgroundColor
}
Write-Host
break
}
'File' {
# Assuming $OFS built-in Variable is an space
write-output "$Text"
break
}
Default {
throw '$OutputType must be "Screen" or "File".'
}
}
}
$CodeBlock = {
param ($OutputType)
Write-Color -T "=== STARTING ===" -C Cyan -B Gray -O $OutputType
Write-Color -T 'Date: ', (Get-Date).ToString('yyyy-MM-dd hh:mm:ss') -C Green, Yellow -O $OutputType
Write-Color -T 'Processing..' -C Cyan -O $OutputType
Write-Color -T 'Date: ', (Get-Date).AddSeconds(3).ToString('yyyy-MM-dd hh:mm:ss') -C Green, Yellow -O $OutputType
Write-Color -T "=== ENDING ===" -C Cyan -B Gray -O $OutputType
}
$Dir = 'D:\Tmp' # Set your output directory
#### Screen Test ####
& $CodeBlock -OutputType 'Screen'
& $CodeBlock -OutputType 'File'
### File Test ####
# This file have unwanted newlines, notice the IO redirection with "*>"
& $CodeBlock -OutputType 'Screen' *> "$Dir\Screen.log"
& $CodeBlock -OutputType 'File' > "$Dir\File.log"