PowerShell 错误变量丢失内容
PowerShell error variable loses the content
我有一个很大的项目,里面有很多功能。
只有 2 个问题:
- 关于错误处理的“最佳实践”是什么?要对每个函数使用本地处理,还是在主部分仅使用一个错误记录?
- 棘手的部分 (!),让我们来看看函数中奇怪的错误行为 F_XXX:只有 $_ 传递错误消息,$Error[0] 在这里是空的!奇怪的是,当我单独启动函数 F_XXX 时(从模块中删除),它的行为符合预期,这意味着: $Error[0] 返回错误。代码:
Blockquote
$ErrorActionPreference = "Stop"
Function F1
{
try
{
# do something
}
catch
{
# 1. cascade Error to Main?
# throw $Error[0].InnerException
# or
# local Error-Logging?
write-MyErrorLogging -message $Error[0].InnerException
}
}
Function F2
{
try
{
# do something
}
catch
{
# 1. cascade Error to Main?
# throw $Error[0].InnerException
# or
# local Error-Logging?
write-MyErrorLogging -message $Error[0].InnerException
}
}
Function F_XXXXXX
{
try
{
cls
write-host "The install data is copied.."
$share = "\my_wrong_path\sql_sources\"
Copy-Item $share -Destination $installDrive -Force -Recurse
}
catch
{
$Error[0] #here is nothing!
$null -eq $Error[0] # here true
$_.Exception # only here the error-message: wrong path!
}
}
Blockquote
# here Main
try
{
F1
F2
F_XXXXXX
}
catch
{
write-MyErrorLogging -message $Error[0].InnerException
}
Blockquote
在catch
块内,最好避免$Error[0]
,给定手头的错误可靠地反映在 automatic $_
variable.
- 如果您确实需要通过 automatic
$Error
variable 访问 previous 错误,请在模块 中使用 $global:Error
-详情见底部。
除非您需要在发生错误时执行 额外的 操作,否则您可以让 script-terminating(致命)错误(您的 $ErrorActionPreference = "Stop"
语句将代码中的 all 错误变成)冒泡调用堆栈,直到它被 try
/ catch
statement 捕获,或者在没有捕获的情况下终止整个调用堆栈(即脚本及其调用者)。
- 如果您确实需要执行其他操作,请使用
try
/ catch
,并将操作放在 catch
块中(以及可能的清理操作 finally
块),然后是 re-throwing 错误,只需调用 throw
而不带参数 .
因此,您可以在脚本的 top-level 范围内使用 single try
/ catch
语句:
# Turn all errors in this and descendant scopes into
# script-terminating (fatal) ones.
$ErrorActionPreference = 'Stop'
# ... other function definitions, without try / catch
# Top-level code that calls the other functions and catches
# any errors.
try
{
F1
F2
F_XXXXXX
}
catch
{
write-MyErrorLogging -message $_.InnerException
}
模块中的automatic $Error
variable:
奇怪的是,至少达到 PowerShell 7.2.3(撰写本文时为当前版本):
模块中发生的错误 - 就像模块外发生的错误一样 - 记录在 [=52= 中存在的 $Error
变量中]全局范围。
然而,一个看似未使用,module-local复制 of $Error
存在,shadows全局变量。
解决方法是在模块.
中使用use $global:Error
鉴于 module-local 副本似乎从未被触及并且没有明显的用途,该行为表明存在错误。
我有一个很大的项目,里面有很多功能。 只有 2 个问题:
- 关于错误处理的“最佳实践”是什么?要对每个函数使用本地处理,还是在主部分仅使用一个错误记录?
- 棘手的部分 (!),让我们来看看函数中奇怪的错误行为 F_XXX:只有 $_ 传递错误消息,$Error[0] 在这里是空的!奇怪的是,当我单独启动函数 F_XXX 时(从模块中删除),它的行为符合预期,这意味着: $Error[0] 返回错误。代码:
Blockquote
$ErrorActionPreference = "Stop"
Function F1
{
try
{
# do something
}
catch
{
# 1. cascade Error to Main?
# throw $Error[0].InnerException
# or
# local Error-Logging?
write-MyErrorLogging -message $Error[0].InnerException
}
}
Function F2
{
try
{
# do something
}
catch
{
# 1. cascade Error to Main?
# throw $Error[0].InnerException
# or
# local Error-Logging?
write-MyErrorLogging -message $Error[0].InnerException
}
}
Function F_XXXXXX
{
try
{
cls
write-host "The install data is copied.."
$share = "\my_wrong_path\sql_sources\"
Copy-Item $share -Destination $installDrive -Force -Recurse
}
catch
{
$Error[0] #here is nothing!
$null -eq $Error[0] # here true
$_.Exception # only here the error-message: wrong path!
}
}
Blockquote
# here Main
try
{
F1
F2
F_XXXXXX
}
catch
{
write-MyErrorLogging -message $Error[0].InnerException
}
Blockquote
在
catch
块内,最好避免$Error[0]
,给定手头的错误可靠地反映在 automatic$_
variable.- 如果您确实需要通过 automatic
$Error
variable 访问 previous 错误,请在模块 中使用$global:Error
-详情见底部。
- 如果您确实需要通过 automatic
除非您需要在发生错误时执行 额外的 操作,否则您可以让 script-terminating(致命)错误(您的
$ErrorActionPreference = "Stop"
语句将代码中的 all 错误变成)冒泡调用堆栈,直到它被try
/catch
statement 捕获,或者在没有捕获的情况下终止整个调用堆栈(即脚本及其调用者)。- 如果您确实需要执行其他操作,请使用
try
/catch
,并将操作放在catch
块中(以及可能的清理操作finally
块),然后是 re-throwing 错误,只需调用throw
而不带参数 .
- 如果您确实需要执行其他操作,请使用
因此,您可以在脚本的 top-level 范围内使用 single try
/ catch
语句:
# Turn all errors in this and descendant scopes into
# script-terminating (fatal) ones.
$ErrorActionPreference = 'Stop'
# ... other function definitions, without try / catch
# Top-level code that calls the other functions and catches
# any errors.
try
{
F1
F2
F_XXXXXX
}
catch
{
write-MyErrorLogging -message $_.InnerException
}
模块中的automatic $Error
variable:
奇怪的是,至少达到 PowerShell 7.2.3(撰写本文时为当前版本):
模块中发生的错误 - 就像模块外发生的错误一样 - 记录在 [=52= 中存在的
$Error
变量中]全局范围。然而,一个看似未使用,module-local复制 of
$Error
存在,shadows全局变量。
解决方法是在模块.
中使用use$global:Error
鉴于 module-local 副本似乎从未被触及并且没有明显的用途,该行为表明存在错误。