Завершение сценария в PowerShell

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

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

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

Edit: Да, это просто exit. Да.

10 ответов


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


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

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

выход vs возвращение vs перерыв

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

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

    Примечание: по умолчанию, если вы щелкните правой кнопкой мыши на скрипте, чтобы запустить его в 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
    }
    

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..."
}

Write-Error предназначен для неустранимых ошибок и бросить для прекращения ошибки

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

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

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


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


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

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

[Environment]::Exit(1)

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


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

throw "Error Message"

это приведет к ошибке завершения.


может быть лучше использовать "ловушку". Ловушка PowerShell указывает codeblock для запуска при завершении или возникновении ошибки. Тип

Get-Help about_trap

чтобы узнать больше о инструкции trap.


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

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

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

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


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

Function Quit($Text) {
    Write-Host "Quiting because: " $Text
    Break Script
}