ChatGPT解决这个技术问题 Extra ChatGPT

“Write-Host”、“Write-Output”或“[console]::WriteLine”有什么区别?

有许多不同的方式来输出消息。通过 Write-HostWrite-Output[console]::WriteLine 输出内容之间的有效区别是什么?

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

write-host "count=" + $count

+ 包含在输出中。为什么?在写出之前,不应该评估表达式以产生单个连接字符串吗?

Write-Output 当您发出结果时。 Write-Host 当您发出日志信息时。切勿使用 [console]::writeline()
@JohnL 为什么我们永远不应该使用 [console]::writeline() ?
@Backwards_Dave 因为你有 Write-Host.... 好吧,我可能有一些印象,它显示了一个新的控制台窗口(这是很久以前的事了)。这不会发生,但事实仍然是它不是 powershell 惯用语,并且您可以用 [console]::writeline("hello world") 做任何事情,而您不能用 Write-Host "hello world" 做任何事情。另一个更好的、最近适用的答案是 write-host 包装了 write-information,因此它的数据被放在像 write-error 这样的流上,这样您就可以捕获它并在其他地方使用它。 [console]::writeline() 不这样做

t
thecoshman

当您想在管道中发送数据但不一定想在屏幕上显示时,应该使用 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 的 video,解释管道的工作原理。当我开始学习 PowerShell 时,我发现这是对管道如何工作的最有用的解释。


在 Azure WebJob [console]::WriteLine 中有效,但 Write-Host 将导致错误:为控制台输出缓冲区设置字符属性时发生 Win32 内部错误“句柄无效”0x6。不要问我为什么。
如果我错了,请纠正我,但我相信 Write-Output 是默认设置,例如,如果您有一个 PsObject 并且您只是通过执行此 $object 将其吐出到屏幕上,它实际上会执行与此 Write-Output $object 相同的操作.可能值得一提
有新的指导:尽可能避免使用 Write-Output。请参阅 github.com/PoshCode/PowerShellPracticeAndStyle/issues/… >仅使用 return 来结束执行。 >避免写输出(...)。相反,当您想让输出更清晰时,只需将输出分配给相关命名的变量即可。并将该变量单独放在一行上以表示显式输出。 > Write-Output -NoEnumerate 在 PowerShell 6 上已损坏,并且已经存在 16 个月或更长时间 - 没有修复它的计划。总之:>永远不要使用写输出。
K
KFL

除了 Andy 提到的之外,还有另一个可能很重要的区别 - write-host 直接写入主机并且不返回任何内容,这意味着您不能将输出重定向到文件。

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

现在在 PowerShell 中运行:

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

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

但是,如果改用 write-output,您将获得重定向按预期工作。


如果您使用 Start-Process Powershell ,则可以捕获写入主机输出。\a.ps1 -RedirectStandardOutput somefile.txt 但是,编码有问题(文件将在 SystemDefaultEncoding 中)。
I
I say Reinstate Monica

这是另一种实现相当于 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,但第三个不会。

“help Write-Output”暗示了这种行为:

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

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


D
Drew Noakes

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

避免使用 Write-Host,因为它可能不适用于所有主机,在没有主机时不起作用,并且(在 PS 5.0 之前)不能被抑制、捕获或重定向。相反,使用 Write-Output、Write-Verbose 或 Write-Information。

有关详细信息,请参阅该规则后面的 documentation。后人摘录:

除非使用带有 Show 动词的命令,否则非常不鼓励使用 Write-Host。 Show 动词明确表示“在屏幕上显示,没有其他可能性”。带有 Show 动词的命令不应用此检查。

Jeffrey Snover 有一篇博文 Write-Host Considered Harmful,其中他声称 Write-Host 几乎总是做错事,因为它会干扰自动化,并在诊断背后提供了更多解释,但以上内容很好概括。


t
tom

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

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

下面是 Write-Host、Write-Output 和 [Console]::WriteLine() 的 5 次测试的结果。

在我有限的经验中,我发现在处理任何类型的现实世界数据时,我需要放弃 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

Write-OutputWrite-Host 的用途不同,因此没有必要比较它们的性能。是的,直接使用 .NET 类型及其方法更快,但您会错过 PowerShell cmdlet 可以提供的高级功能。 [Console]::WriteLine() 在本例中类似于 Write-Host,但并非在所有情况下都有效,因为并非所有 PowerShell 主机都是控制台
M
Mike Twc

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