我一直在寻找一种方法来在函数中发生不可恢复的错误时终止 PowerShell (PS1) 脚本。例如:
function foo() {
# Do stuff that causes an error
$host.Exit()
}
当然,没有 $host.Exit()
这样的东西。有 $host.SetShouldExit()
,但这实际上关闭了控制台窗口,这不是我想要的。我需要的是与 Python 的 sys.exit()
等效的东西,它只会停止执行当前脚本而无需进一步告别。
编辑: 是的,它只是 exit
。呃。
我意识到这是一篇旧帖子,但我发现自己经常回到这个帖子,因为它是搜索这个主题时最热门的搜索结果之一。但是,由于信息相互矛盾,我总是比我来时更加困惑。最终,我总是必须执行自己的测试才能弄清楚。所以这次我将发布我的发现。
TL;DR 大多数人都希望使用 Exit
来终止正在运行的脚本。但是,如果您的脚本只是声明稍后在 shell 中使用的函数,那么您将希望在所述函数的定义中使用 Return
。
退出 vs 返回 vs 休息
退出:这将“退出”当前运行的上下文。如果您从脚本调用此命令,它将退出脚本。如果您从 shell 调用此命令,它将退出 shell。如果一个函数调用 Exit 命令,它将退出它正在运行的任何上下文。因此,如果仅从正在运行的脚本中调用该函数,它将退出该脚本。但是,如果您的脚本仅声明该函数以便可以在当前 shell 中使用它,并且您从 shell 运行该函数,它将退出 shell,因为 shell 是包含 Exit 命令的函数正在运行的上下文。注意:默认情况下,如果您右键单击脚本在 PowerShell 中运行它,一旦脚本运行完毕,PowerShell 将自动关闭。这与 Exit 命令或脚本中的任何其他内容无关。对于使用这种运行脚本的特定方法运行的脚本来说,这只是默认的 PowerShell 行为。批处理文件和命令行窗口也是如此。
Return:这将返回到上一个调用点。如果您从脚本(在任何函数之外)调用此命令,它将返回到 shell。如果您从 shell 调用此命令,它将返回到 shell(这是从 shell 运行的单个命令的前一个调用点)。如果您从函数调用此命令,它将返回到调用函数的位置。在返回的调用点之后执行任何命令将从该点继续。如果从 shell 调用脚本并且它在任何函数之外包含 Return 命令,那么当它返回到 shell 时,就没有更多命令可以运行,因此以这种方式使用的 Return 与 Exit 基本相同。
Break:这将打破循环并切换案例。如果您在不在循环或 switch case 中调用此命令,它将跳出脚本。如果您在嵌套在循环内的循环内调用 Break,它只会跳出被调用的循环。Break 还有一个有趣的功能,您可以在循环前加上标签,然后您可以跳出即使在该标记循环内的多个嵌套组中调用了 Break 命令,该标记循环也是如此。 While ($true) { # 这里的代码将运行 :myLabel While ($true) { # 这里的代码将运行 While ($true) { # 这里的代码将运行 While ($true) { # 这里的代码将运行 Break myLabel # 代码这里不会运行 } # 这里的代码不会运行 } # 这里的代码不会运行 } # 这里的代码会运行 }
您应该使用 the exit
keyword。
Exit -1
或 Exit 1
。 0
以外的任何数字都将 $?
解析为 False
。
sys.exit
的行为类似。 $host.SetShouldExit()
在从控制台运行脚本时关闭控制台窗口。他不想要的。这似乎有我想要的行为......
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..."
}
break
...调用脚本也可能会中断!
Write-Error 用于非终止错误,throw 用于终止错误
Write-Error cmdlet 声明一个非终止错误。默认情况下,错误在错误流中发送到要显示的主机程序,以及输出。非终止错误将错误写入错误流,但它们不会停止命令处理。如果在输入项集合中的一项上声明了非终止错误,则该命令将继续处理该集合中的其他项。要声明终止错误,请使用 Throw 关键字。有关详细信息,请参阅 about_Throw (http://go.microsoft.com/fwlink/?LinkID=145153)。
powershell -command "& module-function ..."
。我需要将这些函数转换为 throw 到一个包装 try-catch 并从该包装 catch 中退出,以便实际输出错误退出代码。
$PSCmdlet.ThrowTerminatingError()
(已知问题,没有来自 throw
的终止错误)
终止此进程并为底层操作系统提供指定的退出代码。
https://msdn.microsoft.com/en-us/library/system.environment.exit%28v=vs.110%29.aspx
[Environment]::Exit(1)
这将允许您使用特定的退出代码退出,该代码可以从调用者处获取。
Exit 1
。
[Environment]::Exit(1)
具有退出我的 powershell 窗口的副作用,而使用 exit
似乎不会这样做。
抛出异常会很好,特别是如果您想澄清错误原因:
throw "Error Message"
这将产生终止错误。
我认为您正在寻找 Return
而不是 Break
。 Break 通常用于循环,并且仅从最里面的代码块中断。使用 Return 退出函数或脚本。
Return
只会从函数返回,而不是从脚本返回。 (脚本 top 级别的 Return
将终止脚本,但这不是问题所在。)
我巧合地发现 Break <UnknownLabel>
(例如只是 Break Script
,标签 Script
不存在的地方)似乎脱离了整个脚本(甚至从函数内部)并保持主机活着。
这样,您可以创建一个函数,在不知道当前范围(并创建标签)的情况下从任何地方(例如递归循环)中断脚本:
Function Quit($Text) {
Write-Host "Quiting because: " $Text
Break Script
}
使用“陷阱”可能会更好。 PowerShell 陷阱指定在发生终止或错误时运行的代码块。类型
Get-Help about_trap
了解有关陷阱语句的更多信息。
我用它来重新运行程序。我不知道它是否会有所帮助,但这是一个简单的 if 语句,只需要两个不同的条目。它对我来说在powershell中工作。
$rerun = Read-Host "Rerun report (y/n)?"
if($rerun -eq "y") { Show-MemoryReport }
if($rerun -eq "n") { Exit }
不知道这是否有帮助,但我相信这类似于在您运行程序后终止程序。但是,在这种情况下,每个定义的输入都需要列出和分类的输出。您还可以让 exit 调用一个新的提示行并以这种方式终止程序。
我想出了一个巧妙的小技巧来做到这一点,当我想要一个函数退出脚本而不抛出错误,但如果从那里使用该函数则不退出控制台。它涉及仅在运行脚本时定义的 $PSScriptRoot
自动变量。
if($PSScriptRoot){exit}
Exit
可以将返回码作为参数(默认为 0) - 例如Exit 3
。Get-Command Exit
和Get-Alias Exit
没有结果。然后我查看它是否是一个关键字,并没有找到关于它的官方文档。然而,现在看它,我不知道我是如何得出这个结论的。显然它是一个关键字 (technet.microsoft.com/en-us/library/hh847744.aspx)。可能是因为 Exit 是唯一没有自己的 about_ 帮助主题的关键字之一,因此左侧边栏中的主题列表不包括它。exit
?