Search code examples
powershelltry-catchexit

Powershell to continue gracefully in case of a try catch


Appologies, this might be a simple thing, but I can't get it working!! I have a much bigger script for the demo purposes I have simplified this. Basically, what I want is that PowerShell to continue and return code 0 and do the write-host even if there is a try catch e.g. in this case I want json_template to print with the Message that includes the error message but the other fields are empty. Currently when I run the script, I get this:

enter image description here

Many thanks and appreciate the response. The code is below:

$hostName = ""

if ([string]::IsNullOrEmpty($hostName)) {
    throw "Host name cannot be null or empty"
}

$json_template = $null

try {
    $nameModel = Get-WmiObject Win32_ComputerSystem -ComputerName $hostName  | select name, model | ConvertTo-Json;
    $serialNumer = Get-WmiObject win32_bios -ComputerName $hostName | select Serialnumber | ConvertTo-Json;

    $json_template = @"
{
  "Info": $($nameModel),
  "Serial": $($serialNumer),
  "Message": ""
}
"@
}
catch {
    $json_template = @"
{
    "Info": "",
    "Serial": "",
    "Message": "$($_.Exception.Message)"
}
"@
    # Gracefully exit with code 0
    #exit 0
}
finally {
    # Print the JSON template
    Write-Host $json_template
    exit 0;
}


Solution

  • The main error is having the Throw outside the Try{}.
    Have a commented version with some, I hope useful, points

    # Managing hard-coded JSON is hard
    # Let's make an empty template Object instead and convert it only when necessary!
    $json_template = [PSCustomObject]@{
        Info    = ''
        Serial  = ''
        Message = ''
    }
    
    
    # Setting up the variable to fail
    $hostName = ''
    
    
    try {
        # Catch is never going to catch the Throw if it's outside the Try
        if ([string]::IsNullOrEmpty($hostName)) { throw 'Host name cannot be null or empty' }
    
        # Two things:
        # 1. Get-WmiObject has been Obsolete for years and removed from
        #    Powershell 6+. Use Get-CimInstance instead.
        # 2. Depending on your system settings you might need tell Cmdlets to
        #    stop(and throw) if they hit an error. You can do it by adding
        #    "-ErrorAction Stop" to each cmdlet or setting it on a global level.
        #    I'll let you look up for that to decide what's the best course of
        #    action case-by-case.
        $json_template.Info = Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName $hostName -ErrorAction Stop | Select-Object -Property Name, Model
        $json_template.Serial = Get-CimInstance -ClassName Win32_BIOS -ComputerName $hostName -ErrorAction Stop | Select-Object -Property SerialNumber
    }
    catch {
        $json_template.Message = $_.Exception.Message
    }
    finally {
        # Convert the whole Object to JSON and send it to be printed on screen
        $json_template | ConvertTo-Json | Write-Host
        exit 0
    }