Home > Software design >  Catch block does not print out Warning message into console after
Catch block does not print out Warning message into console after

Time:01-09

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"
    }
}

CodePudding user response:

  • 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:

  • Advanced (cmdlet-like) functions imported from script modules do not see preference variables, unless they happen to be defined in the global scope - see GitHub issue #4568 for a discussion of this problematic behavior.

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).

  • Related