Завершение скрипта в PowerShell - PullRequest
347 голосов
/ 07 января 2010

Я искал способ завершить сценарий PowerShell (PS1), когда в функции возникает неисправимая ошибка. Например:

function foo() {
    # Do stuff that causes an error
    $host.Exit()
}

Конечно, нет такой вещи как $host.Exit(). Есть $host.SetShouldExit(), но это фактически закрывает окно консоли, а это не то, что я хочу. Что мне нужно, это что-то эквивалентное Python sys.exit(), которое просто прекратит выполнение текущего скрипта без дополнительной информации.

Редактировать: Да, это просто exit. Duh.

Ответы [ 10 ]

524 голосов
/ 16 мая 2014

Я понимаю, что это старая запись, но я часто возвращаюсь к этой теме, поскольку она является одним из лучших результатов поиска при поиске по этой теме. Однако я всегда оставляю более смущенным, чем когда приходил из-за противоречивой информации. В конечном счете, я всегда должен выполнять свои собственные тесты, чтобы понять это. Поэтому на этот раз я опубликую свои выводы.

TL; DR Большинство людей захотят использовать Exit для завершения запущенных сценариев. Однако, если ваш скрипт просто объявляет функции, которые впоследствии будут использоваться в оболочке, тогда вы захотите использовать Return в определениях указанных функций.

Выход против возврата против перерыва

  • Выход: Это «завершит» текущий запущенный контекст. Если вы вызываете эту команду из скрипта, он выйдет из скрипта. Если вы вызовете эту команду из оболочки, она выйдет из оболочки.

    Если функция вызывает команду Exit, она выходит из любого контекста, в котором она запущена. Поэтому, если эта функция вызывается только из запущенного скрипта, она выйдет из этого скрипта. Однако, если ваш скрипт просто объявляет функцию, чтобы ее можно было использовать из текущей оболочки, и вы запускаете эту функцию из оболочки, он выйдет из оболочки, потому что оболочка - это контекст, в котором функция, составляющая команду Exit, работает.

    Примечание: По умолчанию, если щелкнуть правой кнопкой мыши сценарий, чтобы запустить его в PowerShell, после его запуска PowerShell автоматически закроется. Это не имеет ничего общего с командой Exit или чем-либо еще в вашем скрипте. Это просто поведение PowerShell по умолчанию для сценариев, запускаемых с использованием этого конкретного метода запуска сценария. То же самое верно для командных файлов и окна командной строки.

  • Возврат: Это вернет к предыдущему пункту вызова. Если вы вызовете эту команду из скрипта (вне каких-либо функций), она вернется в оболочку. Если вы вызовете эту команду из оболочки, она вернется в оболочку (которая является предыдущей точкой вызова для одной команды, запущенной из оболочки). Если вы вызываете эту команду из функции, она вернется туда, откуда была вызвана функция.

    Выполнение любых команд после точки вызова, в которую она возвращается, будет продолжено с этой точки. Если скрипт вызывается из оболочки и содержит команду Return вне каких-либо функций, то при возврате в оболочку команды больше не выполняются, поэтому Return, используемый таким образом, по существу такой же, как Exit .

  • Перерыв: Это приведет к разрыву петель и переключению корпусов. Если вы вызываете эту команду, не находясь в цикле или переключении, она выйдет из сценария. Если вы вызываете Break внутри цикла, который вложен в цикл, он будет прерываться только из цикла, в котором он был вызван.

    Существует также интересная особенность Break, в которой вы можете поставить префикс цикла с меткой, а затем выйти из этого помеченного цикла, даже если команда Break вызывается в нескольких вложенных группах внутри этого помеченного цикла.

    While ($true) {
        # Code here will run
    
        :myLabel While ($true) {
            # Code here will run
    
            While ($true) {
                # Code here will run
    
                While ($true) {
                    # Code here will run
                    Break myLabel
                    # Code here will not run
                }
    
                # Code here will not run
            }
    
            # Code here will not run
        }
    
        # Code here will run
    }
    
340 голосов
/ 07 января 2010

Вы должны использовать ключевое слово exit .

75 голосов
/ 20 октября 2012

Exit также выйдет из PowerShell. Если вы хотите «разорвать» только текущую функцию или скрипт - используйте Break:)

If ($Breakout -eq $true)
{
     Write-Host "Break Out!"
     Break
}
ElseIf ($Breakout -eq $false)
{
     Write-Host "No Breakout for you!"
}
Else
{
    Write-Host "Breakout wasn't defined..."
}
46 голосов
/ 13 декабря 2013

Ошибка записи - для не прекращающихся ошибок, а throw - для завершающих ошибок

Командлет Write-Error объявляет нескончаемую ошибку. По умолчанию, ошибки передаются в потоке ошибок в хост-программу отображается вместе с выводом.

Не прекращающиеся ошибки записывают ошибку в поток ошибок, но они не останавливают обработку команд. Если не прекращающаяся ошибка объявляется один элемент в коллекции входных элементов, команда продолжает обрабатывать другие элементы в коллекции.

Чтобы объявить завершающая ошибка, используйте ключевое слово Throw. Для получения дополнительной информации см. about_Throw (http://go.microsoft.com/fwlink/?LinkID=145153).

25 голосов
/ 25 февраля 2015

Завершает этот процесс и дает базовой операционной системе указанный код выхода.

https://msdn.microsoft.com/en-us/library/system.environment.exit%28v=vs.110%29.aspx

[Environment]::Exit(1)

Это позволит вам выйти с определенным кодом выхода, который можно получить у звонящего.

24 голосов
/ 06 мая 2013

Я думаю, что вы ищете Return вместо Break.Разрыв обычно используется для циклов и разрывается только от самого внутреннего блока кода.Используйте Return для выхода из функции или скрипта.

20 голосов
/ 31 октября 2014

Бросок исключения будет хорошо, особенно если вы хотите выяснить причину ошибки:

throw "Error Message"

Это приведет к завершающей ошибке.

12 голосов
/ 09 января 2010

Может быть, лучше использовать «ловушку». Ловушка PowerShell задает кодовый блок, который запускается при завершении или ошибке. Тип

Get-Help about_trap

чтобы узнать больше об операторе trap.

5 голосов
/ 11 июля 2017

По совпадению я обнаружил, что Break <i><UnknownLabel></i> (например, просто Break <b>Script</b>, , где метка Script не существует ), кажется, выходит из всего сценария (даже внутри функции) и поддерживает хозяина в живых.
Таким образом, вы можете создать функцию, которая разрывает скрипт из любого места (например, рекурсивный цикл), не зная текущей области (и создавая метки):

Function Quit($Text) {
    Write-Host "Quiting because: " $Text
    Break Script
} 
3 голосов
/ 05 декабря 2015

Я использовал это для перезапуска программы. Я не знаю, поможет ли это, но это простое утверждение if, требующее только двух разных записей. Это сработало в PowerShell для меня.

$rerun = Read-Host "Rerun report (y/n)?"

if($rerun -eq "y") { Show-MemoryReport }
if($rerun -eq "n") { Exit }

Не знаю, поможет ли это, но я верю, что это будет похоже на завершение программы после ее запуска. Однако в этом случае каждый определенный вход требует перечисленных и категоризированных выходных данных. Вы могли бы также вызвать exit, вызвав новую строку приглашения и завершив программу таким образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...