问题
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:
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.
来源:https://stackoverflow.com/questions/19939886/powershell-try-catch-continue