我已经阅读了很多有关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 { ... }
假设对于传递给此函数的每台计算机名称,我有4个任务要完成,但是如果任何一个任务失败,我将无法继续执行其余任务。 我应该如何产生一个错误(最佳实践),使该特定计算机名称的“进程”暂停,但有效地继续处理管道?
答案 0 :(得分:1)
如果要继续处理管道中的输入,则必须发出非终止错误:
> Write-Error
写入非终止错误;它写入PowerShell的错误流,而不会在后台生成异常;执行正常继续。
如果.NET方法调用是错误源,例如您的情况,请将其包装在try
/ catch
中,然后在{{1}中调用Write-Error -ErrorRecord $_
}区块:
catch
不幸的是,从PowerShell Core 7.0.0-preview.4开始,try { <#task 1 #>; ... } catch { Write-Error -ErrorRecord $_ }
仍未完全按预期运行,因为它没有设置自动成功状态变量{{ 1}},并在调用者的上下文中Write-Error
。当前唯一的解决方法是确保您的函数/脚本是advanced,并使用$?
;通过$false
块中的 您可以简单地使用$PSCmdlet.WriteError()
,但是从头开始编写自己的错误很麻烦-请参见this GitHub issue。
如果要立即停止处理,请使用终止错误:
catch
创建终止错误。
不幸的是,$PSCmdlet.WriteError($_)
产生的终止错误类型比二进制cmdlet发出的错误类型更多:不同于(em> statement 声明的终止错误,由(compiled )cmdlet,throw
会创建一个 script 终止错误(运行空间终止错误)
throw
则默认终止整个脚本(及其调用方)。 同样,解决方法要求您的脚本/函数是高级脚本,因此您可以调用throw
而不是throw
,这样可以正确生成一个声明终止错误;与$PSCmdlet.ThrowTerminatingError()
一样,您可以简单地从throw
块中使用$PSCmdlet.WriteError()
,但是从头开始编写自己的语句终止错误很麻烦。
关于$PSCmdlet.ThrowTerminatingError($_)
这会将所有错误类型转换为 script 终止错误,以及至少 高级函数/脚本-预期会像cmdlet一样工作-应该不要设置。
相反,让脚本/函数发出适当类型的错误,并让调用方通过常见的catch
参数或{ {1}}变量。
关于从功能脚本内部通过 / 重新包装传递错误:
非终止错误会自动传递。
$ErrorActionPreference = 'Stop'
或-ErrorAction
禁止显示它们,还可以选择使用$ErrorActionPreference
公用参数(与-ErrorAction Ignore
组合)收集它们以供以后处理。 / li>
脚本终止的错误会通过整个运行空间以及代码的终止来传递。
声明-终止错误被写入错误流,但是默认情况下,脚本/函数继续继续运行。
使用2>$null
来将其转换为 script 终止错误,或者...
...使用-ErrorVariable
而不是-ErrorAction SilentlyContinue
来将错误作为声明终止。
进一步阅读:
关于何时发出终止与非终止错误的指南在this answer中。
PowerShell错误处理的全面概述在this GitHub docs issue中。
答案 1 :(得分:-1)
使用Try ... Catch-确保所有命令都使用-ErrorAction Stop
开关或将环境设置为在发生错误时停止,例如$ErrorActionPreference = 'Stop'
function Set-ComputerTestConfig {
[CmdletBinding()]
param(
[Parameter(Position=0, Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $Name)
begin { ... }
process {
Try {
# task 1
# task 2 => results in a failure that prevents further tasks
# task 3
# task 4
}
Catch {
Write-Host "One of the tasks has failed`nError Message:"
Write-Host $_
}
}
end { ... }