我是 powershell 的新手,似乎对它的管道概念不太熟悉。据我了解:
Write-Host
写着“在控制台上”,但是不可重复使用/捕获来自其他脚本Write-Output
将某些内容放入管道。如果管道的内容未在其他地方使用,则将其转储到控制台。调用脚本可以使用输出。
我知道,几乎所有的脚本语言都可以从任何地方向控制台写入数据,通过调用脚本来使用,而且不会影响函数的返回值。
所以:
- 这样做有什么好处?目前,它的设计看起来很优雅,但实用性不强。
- 如何在不影响其返回值的情况下从函数内部写入脚本输出(不,我不能使用
[Write-Host][1]
) 我怎样才能在回调/事件中写入脚本输出,例如
$ect = Register-ObjectEvent -InputObject $ps -Action { Write-Somewhere $EventArgs.Data } -EventName 'ErrorDataReceived'
背景:脚本是从包装器文件调用的,是从 Jenkins 调用的包装器文件调用的。Write-Output 已正确记录,但我不能在任何地方使用它。我想避免将文本转储到临时文件中,并在最后将其读回以节省时间。
答案1
Write-Host
和之间的区别的一个有益效果Write-Output
是,您可以Write-Host
在函数中插入日志记录(),而不会弄乱它们实际返回给调用者的值(Write-Output
)。
说到返回给调用者,只需让值从表达式或 cmdlet 调用中出来,它就会作为输出传递。因此,5
单独一行,和Write-Output 5
是等效的。一个有点棘手的概念是,PowerShell 脚本没有与大多数编程语言相同的返回值。使用关键字返回值Return
与允许值输出管道然后退出函数没有区别。换句话说,5; break
与相同Return 5
。脚本输出(可能是多个对象)是返回值。
来自注册为事件操作的脚本块的对象会自动存储在事件的作业对象的属性中,如果您使用提供脚本块Output
,则会从该属性中获取返回值。以下是每次计时器触发时记录当前日期和时间的示例脚本:Register-ObjectEvent
-Action
$timer = New-Object System.Timers.Timer
$timer.Interval = 2000
$myEvent = Register-ObjectEvent $timer -EventName 'Elapsed' -Action {Get-Date}
$timer.Start()
变量$myEvent
将从 接收作业对象Register-ObjectEvent
。$myEvent.Output
将是一个不断增长的时间数组,每次运行Get-Date
事件处理程序时都会有一个时间数组。(有一些自动定义的变量这在这样的处理程序中可能会很有用。)就您而言,一旦生成回调完成,您就可以输出将$ect.Output
捕获的数据传递给调用脚本。
或者,如果您不想处理自定义事件处理程序,则可以省略脚本块,而是提供一个命名事件订阅的源标识符。我们可以$myEvent
用以下代码替换上一个示例中的行:
Register-ObjectEvent $timer -EventName 'Elapsed' -SourceIdentifier 'MyEvent'
现在事件进入事件队列,并标有源标识符。为了稍后检索它们,我们使用Get-Event
:
Get-Event -SourceIdentifier 'MyEvent'
答案2
首先,如果您想了解 Write-Output 的工作原理(以及预期工作原理),请参阅 BenN 的回答。
Write-Output 和 Write-Host 对我来说都不太管用。不过 Powershell 提供了更多屏幕书写和输出通道选项。我选择使用写入详细。我无法控制调用脚本,但幸运的是,详细通道已经合并到标准输出。
如果不是这种情况,您需要手动将调试输出合并到标准输出中:
.\test_writing_to_debug_output.ps1 4>&1 > a_logfile.txt