我正在调用外部.ps1文件,该文件在某些错误条件下包含break
语句。我想以某种方式捕获这种情况,允许任何外部打印的消息显示正常,并继续我的脚本中的后续语句。如果外部脚本有throw
,则使用try
/ catch
可以正常工作。即使我的文件中有trap
,我也无法阻止我的脚本终止。
要回答这个问题,请假设外部.ps1文件的源代码(由其他人创作并在运行时拉入)无法更改。
我想要的是什么,或者是脚本的作者在外部调用时不考虑玩得好吗?
编辑:提供以下示例。
在badscript.ps1中:
if((Get-Date).DayOfWeek -ne "Yesterday"){
Write-Warning "Sorry, you can only run this script yesterday."
break
}
在myscript.ps1中:
.\badscript.ps1
Write-Host "It is today."
我想要实现的结果是看到来自badscript.ps1的警告,并继续使用myscript.ps1中的进一步语句。我明白为什么破坏声明导致“它是今天”。永远不会被打印,但是我想找到一种方法,因为我不是badscript.ps1的作者。
编辑:将标题从“powershell try / catch不捕获break语句”更新为“如何防止外部脚本使用break语句终止脚本”。提及try / catch实际上更多的是关于新标题更好地反映的实际问题的一个失败的解决方案。
答案 0 :(得分:1)
从我的脚本中运行单独的PowerShell进程来调用外部文件最终成为一个足以满足我需求的解决方案:
powershell -File .\badscript.ps1
将执行badscript.ps1的内容,直到break
语句包括任何Write-Host或Write-Warning,然后让我自己的脚本继续。
答案 1 :(得分:1)
PowerShell不限制标签可以恢复执行的距离。的 标签甚至可以跨脚本和函数调用传递控制权 边界。
这让我开始思考:“如何欺骗这种愚蠢的语言设计选择?”。答案是创建一个小的switch
块,该块会在出路时捕获break
:
。\ NaughtyBreak.ps1
Write-Host "NaughtyBreak about to break"
break
。\ OuterScript.ps1
switch ('dummy') { default {.\NaughtyBreak.ps1}}
Write-Host "After switch() {NaughtyBreak}"
.\NaughtyBreak.ps1
Write-Host "After plain NaughtyBreak"
然后,当我们调用OuterScript.ps1时,我们得到
NaughtyBreak about to break
After switch() {NaughtyBreak}
NaughtyBreak about to break
请注意,在对嵌入在交换机中的NaughtyBreak.ps1进行调用之后,OuterScript.ps1可以正确恢复,但是在直接调用NaughtyBreak.ps1时被毫不客气地杀死了。
答案 2 :(得分:1)
将中断放回其所属的循环(包括开关)中。
foreach($i in 1) { ./badscript.ps1 }
'done'
或
switch(1) { 1 { ./badscript.ps1 } }
'done'
答案 3 :(得分:0)
我到达你的来源。可能最简单的方法是将脚本作为工作推出,并等待结果。如果需要,您甚至可以在完成后使用Receive-Job回显结果。
因此,考虑到上面的错误脚本,以及调用它的脚本文件:
$path = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
$start = Start-Job -ScriptBlock { . "$using:Path\badScript.ps1" } -Name "BadScript"
$wait = Wait-Job -Name "BadScript" -Timeout 100
Receive-Job -Name "BadScript"
Get-Command -Name "Get-ChildItem"
这将在作业中执行坏脚本,等待结果,回显结果,然后继续执行它所在的脚本。
这可以包含在您可能需要调用的任何脚本的函数中(只是为了安全起见。
这是输出:
WARNING: Sorry, you can only run this script yesterday.
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Get-ChildItem 3.1.0.0 Microsoft.PowerShell.Management