0

I isolated some code and i have an unexpected behavior.

code:

$objects = @(
    [pscustomobject]@{server="google.com"; some_other_props='some_str'}, 
    [pscustomobject]@{some_other_props='some_str'}, 
    [pscustomobject]@{server='google.com'; some_other_props='some_str'}
)

$objects | % {
    try{
        $result = Test-Connection $_.server
    }catch [System.Management.Automation.ParameterBindingException] {
        Write-Host "no server to ping"
    }
    if($result){
        Write-Host ok
    }
}

expected output:

ok
no server to ping
ok

real ouput:

ok
no server to ping
ok
ok

What am i doing wrong here? from where is the 3rd ok coming??

1
  • 1
    if($result) ... That should go inside the try block. Commented May 9, 2020 at 23:14

3 Answers 3

2

Your catch doesn't break the current execution, so your if statement will run regardless of if the code throws an exception.

Put your if statement at the bottom inside your catch instead.

$objects | % { 
    try{ 
        $result = Test-Connection $_.server 
        if($result) { 
            Write-Host ok 
        }
    } catch [System.Management.Automation.ParameterBindingException] { 
        Write-Host "no server to ping"
    }  
}
Sign up to request clarification or add additional context in comments.

2 Comments

That works, but i still don't understand why my code doesn't work. On the 2 second execution of the loop $result= should be $null. And it shouldnt print 3 * 'OK'... can somebody explain me why it $result seems to be not $null in the 2nd execution of the loop.
Hey @GerritGeeraerts, the reason that is occurring is that the $result variable isn't being updated if an exception is thrown. It's still set to the output of the first object. You can see for yourself by putting a Write-Host $result on the line below your catch closing }
0

You need to add parameter -ErrorAction Stop at the end of the Test-Connection cmdlet in order to redirect both terminating and non-terminating errors to the catch block.

Also, your code explicity catches one type of error, so if anything goes wrong, the code will output "no server to ping", even if that is not the case.

You can add another catch block to also display the other exception messages:

$objects = @(
    [pscustomobject]@{server="google.com"; some_other_props='some_str'}, 
    [pscustomobject]@{some_other_props='some_str'}, 
    [pscustomobject]@{server='google.blah'; some_other_props='some_str'}
)

$objects | ForEach-Object {
    $server = $_.server
    try{
        $result = Test-Connection $server -Count 1 -ErrorAction Stop
        if ($result) {
            Write-Host "Ping '$server': OK"
        }
    }
    catch [System.Management.Automation.ParameterBindingException] {
        Write-Host "No server to ping"
    }
    catch {
        Write-Host "Ping '$server': ERROR:  $($_.Exception.Message)"
    }
}

Output:

Ping 'google.com': OK
No server to ping
Ping 'google.blah': ERROR:  Testing connection to computer 'google.blah' failed: Host is unknown

Comments

0

test-connection doesn't generate a script-terminating or command-terminating exception. Microsoft.com is classically unpingable.

try { test-connection microsoft.com -Count 1 } catch { 'no' }

test-connection : Testing connection to computer 'microsoft.com' failed: Error due to lack of resources
At line:1 char:6
+ try {test-connection microsoft.com -Count 1 } catch { 'no' }
+      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (microsoft.com:String) [Test-Connection], PingException
    + FullyQualifiedErrorId : TestConnectionException,Microsoft.PowerShell.Commands.TestConnectionCommand

You can use the -quiet option to return a boolean and use an if statement instead. Although even without the -quiet, it would work, since the standard output is non-null if the host is up.

if (test-connection microsoft.com -Count 1 -Quiet) {'yes'
} else {'no'}

no

Suprisigly, the '||' operator in Powershell 7 won't work here, because $? is always true after running the command.

test-connection microsoft.com -count 1 -quiet || 'no'

False

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.