Reputation: 559
I have a quite big project with many functions in there. Just 2 questions:
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
Upvotes: 1
Views: 808
Reputation: 439317
Inside a catch
block, it's best to avoid $Error[0]
, given that the error at hand is reliably reflected in the automatic $_
variable.
$Error
variable, use $global:Error
inside modules - see the bottom section for details.Unless you need to perform additional actions when an error occurs, you can let a script-terminating (fatal) error (which your $ErrorActionPreference = "Stop"
statement turns all errors in your code into) bubble up the call stack until it is either caught by a try
/ catch
statement or, in the absence of one, terminates the entire call stack (i.e., the scripts and its callers).
try
/ catch
, and place the actions inside the catch
block (as well as potential cleanup actions in a finally
block), followed by re-throwing the error simply by calling throw
without an argument.Thus, you can make do with a single try
/ catch
statement in the top-level scope of your script:
# 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
}
The automatic $Error
variable in modules:
Strangely, up to at least PowerShell 7.2.3 (current as of this writing):
Errors occurring in modules - just like ones occurring outside modules - are recorded in the $Error
variable that exists in the global scope.
However, a seemingly unused, module-local copy of $Error
exists, which shadows the global variable, both in Windows PowerShell and in PowerShell (Core) up to at least v7.3.7 (current as of this writing). See this answer for the history behind this problem, and GitHub issue #20458 for a discussion about fixing it.
The workaround is to use use $global:Error
from inside modules.
The behavior suggests a bug, given that the module-local copy is seemingly never touched and serves no apparent purpose.
Upvotes: 3