Как предотвратить внешний script от завершения вашего script с помощью оператора break
Я вызываю внешний файл .ps1, содержащий инструкцию break
в определенных условиях ошибки. Я хотел бы как-то поймать этот сценарий, разрешить любые сообщения, напечатанные извне, как обычно, и продолжить с последующими утверждениями в моем script. Если внешний script имеет throw
, это работает отлично, используя try
/catch
. Даже с trap
в моем файле я не могу остановить завершение script.
Чтобы ответить на этот вопрос, предположим, что исходный код внешнего файла .ps1 (созданный кем-то другим и втянутый во время выполнения) не может быть изменен.
Является ли то, что я хочу, или автор script просто не думал о том, чтобы играть красиво, когда вызывается извне?
Изменить: укажите следующий пример.
В файле 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" на "как предотвратить внешний script от завершения вашего script с помощью оператора break". Упоминание try/catch было действительно больше об одном неудавшемся решении фактического вопроса, который лучше отражает новый заголовок.
Ответы
Ответ 1
Я получаю, откуда вы. Вероятно, самым простым способом было бы отключить script как задание и дождаться результатов. Вы даже можете повторить результаты с помощью Receive-Job после этого, если хотите.
Итак, учитывая плохой script, который у вас выше, и этот script файл вызывает его:
$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"
Это приведет к неудачному script в задании, дождитесь результатов, повторит результаты и продолжит выполнение script.
Это может быть завернуто в функцию для любых скриптов, которые вам могут потребоваться (просто чтобы быть в безопасности).
Здесь вывод:
WARNING: Sorry, you can only run this script yesterday.
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Get-ChildItem 3.1.0.0 Microsoft.PowerShell.Management
Ответ 2
Запуск отдельного процесса PowerShell из моего script для вызова внешнего файла оказался подходящим решением для моих нужд:
powershell -File .\badscript.ps1
будет выполнять содержимое файла badscript.ps1 до тех пор, пока инструкция break
, включая любой Write-Host или Write-Warning, и пусть мой собственный script продолжит.
Ответ 3
В документации about_Break говорится
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
Обратите внимание, что OuterScript.ps1 правильно возобновил работу после вызова NaughtyBreak.ps1, встроенного в коммутатор, но был убит бесцеремонно при непосредственном вызове NaughtyBreak.ps1.
Ответ 4
Положить разрыв обратно в цикл (включая переключатель), где он принадлежит.
foreach($i in 1) { ./badscript.ps1 }
'done'