“写主机”,“写输出”或“ [控制台] :: WriteLine”之间有什么区别?


192

有多种不同的输出消息的方式。是通过什么东西输出之间的有效差异Write-HostWrite-Output[console]::WriteLine

我还注意到,如果我使用:

write-host "count=" + $count

+被包括在输出。为什么?在写出表达式之前,不应该对表达式求值以生成单个串联字符串吗?


4
Write-Output当您发布结果时。Write-Host当您发出日志记录信息时。永远不要使用[console]::writeline()
JohnL

2
@JohnL为什么我们永远不要使用[console] :: writeline()?
David Klempfner '16

3
@Backwards_Dave因为您有Write-Host。...好吧,我可能已经对它显示了一个新的控制台窗口(这是很久以前的印象)了。不会发生这种情况,但是事实仍然是,这不是Powershell惯用语,并且[console]::writeline("hello world")您无能为力Write-Host "hello world"。另一个更好的,最近更适用的答案是write-host包装,write-information以便将其数据像放在流中一样放置,write-error以便您可以捕获它并在其他地方使用它。[console]::writeline()不这样做
JohnL

Answers:


267

Write-Output当您要在管道上发送数据,但不一定要在屏幕上显示数据时,应使用。out-default如果没有其他人首先使用它,则管道最终会将其写入。

Write-Host 当您想做相反的事情时应该使用。

[console]::WriteLine本质上Write-Host是幕后工作。

运行此演示代码并检查结果。

function Test-Output {
    Write-Output "Hello World"
}

function Test-Output2 {
    Write-Host "Hello World" -foreground Green
}

function Receive-Output {
    process { Write-Host $_ -foreground Yellow }
}

#Output piped to another function, not displayed in first.
Test-Output | Receive-Output

#Output not piped to 2nd function, only displayed in first.
Test-Output2 | Receive-Output 

#Pipeline sends to Out-Default at the end.
Test-Output 

您需要将连接操作括在括号中,以便PowerShell在对的参数列表进行标记化之前处理该连接Write-Host,或者使用字符串插值

write-host ("count=" + $count)
# or
write-host "count=$count"

顺便说一句-观看Jeffrey Snover的这段视频,解释管道的工作原理。回到我开始学习PowerShell时,我发现这是关于管道如何工作的最有用的解释。


在Azure WebJob中[控制台] :: WriteLine可以使用,但是Write-Host将导致错误:设置控制台输出缓冲区的字符属性时,发生Win32内部错误“句柄无效” 0x6。不要问我为什么。
吉尔·罗伊托

如果我错了,请纠正我,但是我相信这Write-Output是默认设置,例如,如果您有PsObject并通过执行此操作$object将其吐到屏幕上,则它实际上将执行此操作Write-Output $object。可能值得一提
Kolob Canyon

1
有新指南:请Write-Output尽可能避免使用。参见github.com/PoshCode/PowerShellPracticeAndStyle/issues/… >仅将return用于结束执行。>避免写输出(...)。相反,当您想使输出更清晰时,只需将输出分配给相关命名的变量即可。并将该变量单独放在一行上以表示显式输出。> Write-Output -NoEnumerate在PowerShell 6上已损坏,已经使用了16个月或更长时间-没有计划对其进行修复。总结:>请勿使用写入输出-永远。
Jeroen Wiert Pluimers,

28

除了Andy提到的内容外,还有另一个可能很重要的区别-写主机直接写到主机,什么也不返回,这意味着您不能将输出重定向到例如文件。

---- script a.ps1 ----
write-host "hello"

现在在PowerShell中运行:

PS> .\a.ps1 > someFile.txt
hello
PS> type someFile.txt
PS>

如图所示,您无法将它们重定向到文件中。对于一个不小心的人来说,这也许令人惊讶。

但是,如果改用写输出代替,您将获得预期的重定向工作。


如果使用Start-Process Powershell,则可以捕获Write-Host输出。\ a.ps1 -RedirectStandardOutput somefile.txt尽管编码存在问题(文件将位于SystemDefaultEncoding中)。
MKesper '16

16

这是完成Write-Output等效的另一种方法。只需将您的字符串用引号引起来:

"count=$count"

您可以通过运行以下实验来确保其与Write-Output相同:

"blah blah" > out.txt

Write-Output "blah blah" > out.txt

Write-Host "blah blah" > out.txt

前两个输出“ blah blah”到out.txt,但第三个不输出。

“帮助Write-Output”给出了这种行为的提示:

此cmdlet通常在脚本中使用,以在控制台上显示字符串和其他对象。但是,由于默认行为是在管道的末尾显示对象,因此通常不必使用cmdlet。

在这种情况下,字符串本身“ count = $ count”是管道结尾处的对象,并显示出来。


6

对于的用法Write-Host,将PSScriptAnalyzer产生以下诊断:

避免使用Write-Host它,因为它可能无法在所有主机上运行,​​在没有主机的情况下也无法运行,并且(PS 5.0之前的版本)不能被抑制,捕获或重定向。相反,使用Write-OutputWrite-VerboseWrite-Information

有关更多信息,请参见该规则背后的文档。后代节选:

使用的Write-Host,除非在使用命令的与大大气馁Show动词。该Show动词明确表示“在屏幕上显示,没有其他可能性”。

具有Show动词的命令没有应用此检查。

Jeffrey Snover在博客文章Write-Host被认为有害,他在其中声称Write-Host几乎总是错误的做法,因为它会干扰自动化并在诊断后提供更多解释,但是以上内容是一个很好的总结。


3

根据我的测试,Write-Output和[Console] :: WriteLine()的性能比Write-Host好得多。

根据需要写出多少文本,这可能很重要。

下面是否是5个测试结果分别针对Write-Host,Write-Output和[Console] :: WriteLine()进行测试。

以我有限的经验,我发现在处理任何种类的现实世界数据时,我都需要放弃cmdlet并直接使用较低级别的命令,以从脚本中获得任何出色的性能。

measure-command {$count = 0; while ($count -lt 1000) { Write-Host "hello"; $count++ }}

1312ms
1651ms
1909ms
1685ms
1788ms


measure-command { $count = 0; while ($count -lt 1000) { Write-Output "hello"; $count++ }}

97ms
105ms
94ms
105ms
98ms


measure-command { $count = 0; while ($count -lt 1000) { [console]::WriteLine("hello"); $count++ }}

158ms
105ms
124ms
99ms
95ms

1
Write-OutputWrite-Host有不同的用途,因此比较它们的效果毫无意义。是的,直接使用.NET类型及其方法更快,但是您会错过PowerShell cmdlet可以提供的高级功能。[Console]::WriteLine()类似于Write-Host手头的情况,但并非在所有情况下都可以使用,因为并非所有PowerShell主机都是控制台
mklement0 '18年

0

关于[Console] :: WriteLine()-如果要在CMD中使用管道(而不是在Powershell中),则应使用它。假设您希望ps1将大量数据流传输到stdout,并使用其他实用程序来使用/转换它。如果在脚本中使用Write-Host,则速度会慢很多。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.