I am writing a simple script that checks for a local user account. I would like to use the try_catch error to handle errors but I am not able to figure out why the catch block in my script won't print out the warning message in the script. Any guidance is appreciated.
function checkAccount($user)
{
try {
Get-CimInstance Win32_UserAccount| Where-Object -Property Name -Contains $user |Select-Object -ExpandProperty Name -ErrorAction Stop
}
catch {
Write-Warning -Message "Oops, ran into an issue"
}
}
There are two commands that could report non-terminating errors in your pipeline - Get-CimInstance
and Select-Object
[1] - so you should use -ErrorAction Stop
with both.
A simpler alternative is to set the $ErrorActionPreference
preference variable to 'Stop'
for your entire function:
function checkAccount($user)
{
# Make all errors in this scope (and descendant scopes) (script)-terminating,
# which enables them to be caught with try / catch.
$ErrorActionPreference = 'Stop'
try {
Get-CimInstance Win32_UserAccount |
Where-Object -Property Name -eq $user |
Select-Object -ExpandProperty Name
}
catch {
Write-Warning -Message "Oops, ran into an issue"
}
}
Also note that I've replaced -Contains
with -eq
, given that the -contains
operator is for testing if a collection contains a given value, whereas you're processing the user accounts one by one.
If, by contrast, your intent is to perform substring matching, use something -like *$user*
instead.
Caveat:
If, by contrast, your intent was simply to test if a given user account exists, you could define your function as follows, using the approved verb Test
and - accordingly - making the function return a [bool]
value ($true
or $false
):
function Test-Account($user)
{
[bool] (
Get-CimInstance Win32_UserAccount |
Where-Object -Property Name -eq $user
)
}
The commands involved will not report errors under normal conditions, so there's no need for explicit error handling.
The [bool]
cast takes advantage of PowerShell's to-Boolean conversion rules and the fact that a (non-primitive) object converts to $true
, whereas lack of output or $null
convert to $false
- see the bottom section of this answer for a summary of the conversion rules.
[1] Get-CimInstance
should normally only report an error for an invalid class name, and Select-Object -ExpandProperty
only for a non-existent property name (unlike with -Property
). The Where-Object
call should never report an error, given that it doesn't enforce the existence of the specified property (however, with invalid syntax any cmdlet call would report a statement-terminating error).