什么';在powershell模块函数中发出错误的正确方法是什么?
我已经读了很多关于powershell错误处理的书,现在我对在任何给定情况下应该做什么(错误处理)感到非常困惑。我正在使用powershell 5.1(而不是core)。 话虽如此: 假设我有一个模块,其函数类似于以下模拟:什么';在powershell模块函数中发出错误的正确方法是什么?,powershell,powershell-5.0,Powershell,Powershell 5.0,我已经读了很多关于powershell错误处理的书,现在我对在任何给定情况下应该做什么(错误处理)感到非常困惑。我正在使用powershell 5.1(而不是core)。 话虽如此: 假设我有一个模块,其函数类似于以下模拟: function Set-ComputerTestConfig { [CmdletBinding()] param( [Parameter(Position=0, Mandatory=$true)] [ValidateNotNullOrEmpty()
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个任务要完成,但是如果其中任何一个任务失败,我就不能继续执行其余的任务。
我应该如何产生一个错误(最佳实践),使其停止对该特定计算机名的“处理”,但有效地继续处理管道 使用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 { ... }
- 如果要继续处理来自管道的输入,必须发出非终止错误:
写入非终止错误;它写入PowerShell的错误流,而不会在幕后生成异常;执行继续正常进行写入错误
- 如果.NET方法调用是错误源(如您的情况),请将其包装在
/try
中,并在catch
块中调用catch
Write error-ErrorRecord$:
try{;..}catch{Write Error-ErrorRecord$\u}
- 不幸的是,从PowerShell Core 7.0.0-preview.4开始,
并没有完全按照预期运行,因为它没有在调用方上下文中将自动成功状态变量写入错误
设置为$?
。目前唯一的解决方法是确保您的函数/脚本是一个,并使用$false
;从$PSCmdlet.WriteError()
块中,您可以简单地使用catch
,但是从头开始创建自己的错误非常麻烦-请参阅$PSCmdlet.WriteError($\uq)
- 如果.NET方法调用是错误源(如您的情况),请将其包装在
- 如果要立即停止处理,请使用终止错误:
创建终止错误。throw
- 不幸的是,
创建了一种比二进制cmdlet发出的更基本的终止错误:与(编译)cmdlet发出的终止错误语句不同,throw
创建了一个脚本终止(致命)错误throw
- 也就是说,默认情况下,二进制cmdlet的语句终止错误只会终止手头的语句(管道)并继续执行封闭脚本,而默认情况下,
会中止整个脚本(及其调用者)throw
- 讨论这种不对称性
- 也就是说,默认情况下,二进制cmdlet的语句终止错误只会终止手头的语句(管道)并继续执行封闭脚本,而默认情况下,
- 同样,该解决方案要求您的脚本/函数是高级脚本/函数,这使您能够调用
,而不是$PSCmdlet.throwterminingerror()
,从而正确生成语句终止错误;与使用throw
一样,您只需从$PSCmdlet.WriteError()
块中使用catch
,但从头开始编写自己的语句终止错误非常麻烦$PSCmdlet.throwterminingerror($\ux)
- 不幸的是,
- 至于
$ErrorActionPreference='Stop'
- 这会将所有错误类型转换为脚本终止错误,并且至少高级函数/脚本(那些预期像cmdlet一样工作的函数/脚本)不应设置它
- 相反,让脚本/函数发出适当类型的错误,并让调用者通过公共
参数或-ErrorAction
变量控制对这些错误的响应$ErrorActionPreference
- 注意事项:如果调用者位于模块外部或不同模块中,则模块中的函数看不到调用者的首选项变量-这一基本问题将在中讨论
- 至于在函数脚本内部传递错误/重新打包错误:
- 非终止错误会自动传递
- 如果需要,您可以使用
或-ErrorAction Ignore
抑制它们,还可以选择使用2>$null
公共参数(与-ErrorVariable
组合)收集它们以供以后处理-ErrorAction SilentlyContinue
- 如果需要,您可以使用
- 脚本终止错误传递的意义是,默认情况下,整个调用堆栈与代码一起终止
- 语句终止错误会写入错误流,但默认情况下脚本/函数会继续运行
- 使用
将它们转换为脚本终止错误,或者try{…}catch{throw}
- 。。。使用
而不是$PSCmdlet.throwterminingerror($\u)
将错误作为终止错误的语句进行中继throw
- 使用
- 非终止错误会自动传递
- 关于何时发出终止错误与非终止错误的指南在中
- 有关PowerShell错误处理的全面概述,请参阅