Description
First of all, let's not have a misleading discussion. The original guideline uses a bad example. Get-ADUser throws an exception when you use the -Identity parameter and it can't find anything. There's obviously no value in writing a warning if you didn't suppress the error, and it's equally silly to let an exception spew and then still test for null -- you need to either suppress the error or use it instead of testing for null.
Let's try a different example. I have a module which requires the user to configure multiple connection strings and a license before it can continue. Imagine that it was this simple to verify that you had, in fact, configured it:
$Config = Get-Content $ConfigurationFile
This will cause an error and an empty variable if the ConfigurationFile doesn't exist, but does not throw (it's not terminating) by default. There are a few ways I could handle that in PowerShell.
For what it's worth: the pythonic way is always to just charge ahead, never test, and just deal with the exceptions (or let them output, if they're clear enough on their own). The old C/C++ way is to always check the hResult
, there are no exceptions. The Java and C# way usually involve handling exceptions, but not quite as aggressively as Python, you would rarely force an exception to happen if you could avoid it by a quick test.
So which of these should be recommended? Incidentally, for the sake of this discussion, please imagine my throw
statement to be your preferred way of exiting a function with extreme prejudice.
Avoid the error:
if(Test-Path $ConfigurationFile) {
$Config = Get-Content $ConfigurationFile
} else {
# We could write a warning and return, but for consistency:
throw "You must configure MyModule first, please call Initialize-MyModule"
}
<# Do the work #>
Of course, if it's best practice to avoid errors when possible, you still have to have a best practice for dealing with them, because it's not always as easy as Test-Path
to avoid them.
Suppress the error and check the output:
if($Config = Get-Content $ConfigurationFile -ErrorAction SilentlyContinue) {
<# Do the work #>
}
# We could have just done ... nothing, but for consistency:
throw "You have to configure MyModule first, please call Initialize-MyModule"
Or I could write that backwards:
if(!($Config = Get-Content $ConfigurationFile -ErrorAction SilentlyContinue)) {
throw "You have to configure MyModule first, please call Initialize-MyModule"
}
<# Do the work #>
Force an exception and catch it
try {
$Config = Get-Content $ConfigurationFile -ErrorAction Stop
} catch {
# Normally you'd be using some information from the exception, but for consistency
throw "You have to configure MyModule first, please call Initialize-MyModule"
}
<# Do the work #>
Deal with the error itself
$Config = Get-Content $ConfigurationFile -ErrorAction SilentlyContinue -ErrorVariable NoConfig
if($NoConfig) {
# Normally you'd be using some information from the error, but for consistency
throw "You should configure MyModule first, please call Initialize-MyModule"
}
<# Do the work #>