0
votes

I have a working powershell script, but when it cannot find a hostname, it throws a non-terminating exception and writes to the screen that that hostname was unable to be found. I want to catch that exception and simply write to the screen: Not Found. Then I want the script to carry on like normal.

Here is the script:

$listOfComputers = IMPORT-CSV test.txt
$b = "2013-09-11"
ForEach($computer in $listOfComputers){
$name = $computer.Name
Write-Host $name -NoNewLine
try{$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $name)}
catch [Exception] {write-host "  Not Found" -foreground blue}
$key = $reg.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Auto Update\\Results\\Install")
$a = $key.GetValue("LastSuccessTime")
$a = $a.Substring(0,10)
if($a -le $b){Write-Host " " $a -foreground magenta}
else{Write-Host " " $a} 
}

Here is the output:

PS C:\PowerShell Scripts> .\windowsUpdates.ps1
OLDBEAR  Not Found
You cannot call a method on a null-valued expression.
At C:\PowerShell Scripts\windowsUpdates.ps1:8 char:1
+ $key =
$reg.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpd

... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull

You cannot call a method on a null-valued expression.
At C:\PowerShell Scripts\windowsUpdates.ps1:9 char:1
+ $a = $key.GetValue("LastSuccessTime")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

You cannot call a method on a null-valued expression.
At C:\PowerShell Scripts\windowsUpdates.ps1:10 char:1
+ $a = $a.Substring(0,10)
+ ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

Any help is appreciated.

1
possible duplicate of Try/catch does not seem to have an effect. The answers regarding ErrorActionPreference will help you. You can set the preference for your whole script, or per-cmdlet.Anthony Neace
I have already tried setting ErrorActionPreference. No use to me, unless I can print to the screen each time that the error happens. With ErrorActionPreference, I was unable to do that.SMPLGRP
...so you did something like try { get-content "Herp" -ErrorAction stop } catch { "Derp" } and that did not give your desired behavior? Because it absolutely should.Anthony Neace

1 Answers

1
votes

Skip the try/catch altogether, and instead test for connectivity before attempting to access the registry. This should speed your script up, as you won't be waiting for a timeout from OpenRemoteBaseKey on systems that are offline.

$listOfComputers = IMPORT-CSV test.txt
$b = "2013-09-11"
ForEach($computer in $listOfComputers){
    $name = $computer.Name
    Write-Host $name -NoNewLine
    if (-not (Test-Connection -computername $name -count 1 -Quiet -ErrorAction SilentlyContinue) {
        write-host "  Not Found" -foreground blue;
        continue;
    }
    $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $name)

    $key = $reg.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Auto Update\\Results\\Install")
    $a = $key.GetValue("LastSuccessTime")
    $a = $a.Substring(0,10)
    if($a -le $b) {
        Write-Host " " $a -foreground magenta
    }
    else {
        Write-Host " " $a;
    } 
}

You could also test connectivity in bulk before hitting the main loop, filtering any computers that aren't accessible out of your list. See my answer over here for a way to do that.