我正在使用Try / Finally在Powershell中编写一个监视脚本,以便在脚本结束时记录消息。该脚本旨在无限期运行,因此我想要一种跟踪意外退出的方法。
其他所有StackOverflow帖子和Help page我都检查了状态:
即使您使用CTRL + C来停止脚本,也会运行Finally块。如果Exit关键字在Catch块中停止脚本,则也会运行Finally块。
在实践中,我没有发现这是真的。我正在使用以下设计的例子来测试它:
Try {
While($True) {
echo "looping"
Start-Sleep 3
}
} Finally {
echo "goodbye!"
pause
}
在 Ctrl + C (无回声,无暂停)后,每次跳过Finally
块,无论是作为保存的脚本运行还是通过内置的Powershell ISE执行时。我得到的唯一输出是:
looping
looping
...(repeat until Ctrl-C)
我显然错过了一些东西,但我不知道它是什么,特别是在这么小的代码片段中。
答案 0 :(得分:4)
正确的答案是 Ctrl + C 打破了管道,正如该链接中所述,echo
使用管道来处理其输出。因此,一旦 Ctrl + C ,写入管道会导致脚本块出错,并且不会处理任何其他命令。因此,不要使用直接向stdout发送输出的命令,并且有很多间接使用管道的命令。另一方面,Write-Host
不使用管道,因此不会抛出错误。
答案 1 :(得分:1)
功能代码
这将为您提供我相信您之后的行为:
Try {
While($True) {
echo "looping"
Start-Sleep 3
}
} Finally {
Write-Host "goodbye!"
pause
}
<强>参考强>
将指定的对象发送到管道中的下一个命令。 如果该命令是管道中的最后一个命令,则对象将显示在控制台中。
将自定义输出写入主机。
Try-Catch-Finally - Syntax note
请注意,按CTRL + C会停止管道。 发送到管道的对象不会显示为输出。 因此,如果包含要显示的语句,例如&#34;最后块已运行&# 34;,即使最后一个块运行,也不会在按CTRL + C后显示。
<强>解释强>
根据TheIncorrigible1的评论和Vesper的回答,关键是 管道已停止 。但这不是因为Write-Output
中的错误。而且我发现它本身并不令人满意。
Out-Host
将产生所需的输出。Finally
块内处理的对象都可以。pause
如果前面有Write-Output
则不会运行。更多代码
在Finally
区块中运行了一些事情来调查行为,并对发生的事情发表评论。
} Finally {
Write-Output "goodbye!" | Out-Default # works fine
pause
}
} Finally {
Write-Output "goodbye!" | Out-Host # works fine
pause
}
} Finally {
pause # works fine
Write-output "goodbye!" # not executed
}
} Finally {
try{
Write-Output "goodbye!" -ErrorAction Stop
}catch{
Write-Host "error caught" # this is not executed.
} # $error[0] after script execution is empty
pause
}
} Finally {
try{
ThisCommandDoesNotExist
}catch{
Write-Host "error caught" # this is executed
} # $error[0] contains CommandNotFoundException
pause
}