Syn*_*tik 3 powershell powershell-5.0
我已经阅读了很多关于 powershell 错误处理的内容,现在我对在任何给定情况下应该做什么(错误处理)感到非常困惑。我正在使用 powershell 5.1(不是核心)。话虽如此:假设我有一个模块,它的功能看起来像这个模拟:
function Set-ComputerTestConfig {
[CmdletBinding()]
param(
[Parameter(Position=0, Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $Name)
begin { ... }
process {
# task 1
# task 2 => results in a failure that prevents further tasks
# task 3
# task 4
}
end { ... }
Run Code Online (Sandbox Code Playgroud)
假设对于我传递给此函数的每台计算机名称,我有 4 个任务要完成,但如果其中任何一个任务失败,我将无法继续执行剩余的任务。我应该如何产生错误(最佳实践),以便它停止此特定计算机名称的“进程”,但有效地继续处理管道?
如果要继续处理来自管道的输入,则必须发出非终止错误:
Write-Error写入非终止错误;它写入 PowerShell 的错误流,而不会在幕后产生异常;执行正常继续。
如果 .NET 方法调用是错误源(如您的情况),请将其包装在try/ 中catch,然后Write-Error -ErrorRecord $_在catch块中调用:
try { <#task 1 #>; ... } catch { Write-Error -ErrorRecord $_ }不幸的是,仍PowerShell核心7.0.0-preview.4的,Write-Error并不完全像预期的那样,因为它不设置自动成功状态变量$?,以$false在调用者的上下文,因为它应该。目前唯一的解决方法是确保您的函数/脚本是高级的并使用$PSCmdlet.WriteError(); 从一个catch块中你可以简单地使用$PSCmdlet.WriteError($_),但从头开始制作你自己的错误很麻烦 - 请参阅GitHub 问题 #3629。
如果您想立即停止处理,请使用终止错误:
throw 产生终止错误。
不幸的是,throw创建一种比二进制 cmdlet 发出的更基本的终止错误:与(编译的)cmdlet 发出的语句终止错误不同,throw创建脚本终止(致命)错误。
throw默认情况下会中止整个脚本(及其调用者)。同样,解决方法要求您的脚本/函数是高级脚本/函数,它使您能够调用$PSCmdlet.ThrowTerminatingError()而不是throw,从而正确生成语句终止错误;与 一样$PSCmdlet.WriteError(),您可以简单地$PSCmdlet.ThrowTerminatingError($_) 从catch块中使用,但是从头开始制作您自己的语句终止错误很麻烦。
至于 $ErrorActionPreference = 'Stop'
这将打开所有的错误类型为脚本-terminating错误,至少先进的功能/脚本-那些有望像cmdlet的-应该不会设置。
相反,让您的脚本/函数发出适当类型的错误,并让调用者通过公共-ErrorAction参数或$ErrorActionPreference变量来控制对它们的响应。
至于从函数脚本内部传递错误/重新打包它们:
非终止错误会自动通过。
-ErrorAction Ignore或抑制它们,也可以2>$null选择收集它们以供以后使用-ErrorVariable公共参数处理(与 结合-ErrorAction SilentlyContinue)。脚本终止错误是在整个调用堆栈默认终止的意义上传递的,连同您的代码。
语句终止错误会写入错误流,但默认情况下您的脚本/函数会继续运行。
用于try { ... } catch { throw }将它们变成脚本终止错误,或者...
...使用$PSCmdlet.ThrowTerminatingError($_)而不是throw将错误作为语句终止。
进一步阅读:
关于何时发出终止与非终止错误的指南在这个答案中。
PowerShell 错误处理的全面概述位于GitHub 文档问题 #1583 中。
| 归档时间: |
|
| 查看次数: |
827 次 |
| 最近记录: |