Solved

I want to learn about exception handling in power shell I am reading and looking over the script now and really dont know what i am doing !

Posted on 2015-02-21
3
179 Views
Last Modified: 2015-03-07
I want this script to just list the found ips and then if it does not find them return a "*"
right now when I run it I get

I am not sure this is even an "exception"


Open in new window


nd
 
Test-Connection : Testing connection to computer '192.168.5x.39' failed: A non-recoverable error occurred during a database lookup
At C:\Users\Bks\Desktop\ipscan.ps1:8 char:47
+     $startip..$endip | foreach{test-connection <<<<  -ComputerName $startsubnet$_ -count 1} | select -expandproperty ipv4address | select -expandproperty ipaddresstostring | foreach{[System.Net.Dns]::GetHostByAddr
ess("$_")}
    + CategoryInfo          : ResourceUnavailable: (192.168.5x.39:String) [Test-Connection], PingException
    + FullyQualifiedErrorId : TestConnectionException,Microsoft.PowerShell.Commands.TestConnectionCommand
 
T$startrange = read-host "Enter a start IP"
$endrange = read-host "Enter an end IP"
$startsubnet = "$($startrange.Split(".")[0]).$($startrange.Split(".")[1]).$($startrange.Split(".")[2])."
$endsubnet = "$($endrange.Split(".")[0]).$($endrange.Split(".")[1]).$($endrange.Split(".")[2])."
if ($startsubnet -eq $endsubnet) {
    $startip = $($startrange.Split(".")[3])
    $endip = $($endrange.Split(".")[3])
    $startip..$endip | foreach{test-connection -ComputerName $startsubnet$_ -count 1} | select -expandproperty ipv4address | select -expandproperty ipaddresstostring | foreach{[System.Net.Dns]::GetHostByAddress("$_")}
} else {
    write-host "Start subnet was not the same as the end subnet"
}
0
Comment
Question by:NAMEWITHELD12
3 Comments
 
LVL 65

Accepted Solution

by:
RobSampson earned 250 total points
ID: 40624073
Hi there, I'm just learning the finer details of Powershell myself, so hopefully I can explain what I have found with the exercise.

First, here is the code I have come up with:
$startrange = read-host "Enter a start IP"
$endrange = read-host "Enter an end IP"
$startsubnet = "$($startrange.Split(".")[0]).$($startrange.Split(".")[1]).$($startrange.Split(".")[2])."
$endsubnet = "$($endrange.Split(".")[0]).$($endrange.Split(".")[1]).$($endrange.Split(".")[2])."
if ($startsubnet -eq $endsubnet) {
    $startip = $($startrange.Split(".")[3])
    $endip = $($endrange.Split(".")[3])
    $startip..$endip | foreach{
        $lastoctet = $_
        $iptest = test-connection -ComputerName $startsubnet$lastoctet -count 1
        try {
            $iptest | select -expandproperty ipv4address -erroraction Stop | select -expandproperty ipaddresstostring | foreach{[System.Net.Dns]::GetHostByAddress("$_")}
        }
        catch {
            #Write-Host "Test-Connection failed for $startsubnet$lastoctet"
            $Prop = [Ordered]@{
                'Hostname'="<UNKNOWN>"
                'Aliases'="{}"
                'AddressList'="{$startsubnet$lastoctet}"
            }
            New-Object PsObject -Property $Prop
        }
    }
} else {
    write-host "Start subnet was not the same as the end subnet"
}

Open in new window


So we've had to break the code down a bit more from the ForEach loop to be able to branch into error handling scenarios.  We use Test-Connection to return the properties of a tested IP.  From trying an invalid IP, we can gather that the ipv4address property does not exist, so the "select -expandproperty ipv4address" fails.  To be able to catch this error, we run that section in a Try block, with the -ErrorAction Stop parameter for the cmdlet we expect to fail.

We do that so that instead of writing the error text, we can output some custom string or object.  In the Catch block, we create a new ordered hash table with the same properties that is otherwise output by a successful connection.  The "New-Object PsObject -Property $Prop" line instructs Powershell to create a new object from that hash table and pass it along the pipeline, which eventually gets output.

Finally, because Powershell identifies the custom object as having all the same properties as the inbuilt, returned object from GetHostByAddress, it automatically puts those together in the output.

Hopefully that helps.  I still have a lot more to learn, but I really like the way you can work along the pipeline with the right commands.

Regards,

Rob.
0
 
LVL 39

Assisted Solution

by:footech
footech earned 250 total points
ID: 40624992
I'm slightly confused by one thing, you say you want the script to list the found ips and then if it does not find them return a "*", but I'm not quite sure what you mean by "found IPs".  Do you mean IPs that you could ping, or IPs that you could resolve to a name?  When testing the conditions, you could treat errors found as different or same.

Rob's on the right path, but the errors can come from two different places:
 1) from the Test-Connection cmdlet
 2) from the [System.Net.Dns]::GetHostByAddress static method

Try/Catch only catches terminating errors, and the error generated by Test-Connection is normally non-terminating, but we can change that by setting the -ErrorAction parameter to Stop.  If we want treat the errors differently, then we either need to make sure only one can occur in a particular Try block, or you can have multiple Catch blocks for a single Try block, each of which is set to handle a particular exception type.

Following along with Rob's suggestion of outputting a custom object with the same properties as that produced when no error is encountered (which is a good one in many cases), you get something like the below.  
Note:  the "{}" seen when outputting certain properties is indicative of an array, so if you're trying to mirror the normal object you may want to take that into account rather than just creating a string with the curly brackets even though it may look the same in some views.  It may be pedantry to correct that, but it may matter during further processing.

$startrange = read-host "Enter a start IP"
$endrange = read-host "Enter an end IP"
$startsubnet = "$($startrange.Split(".")[0]).$($startrange.Split(".")[1]).$($startrange.Split(".")[2])."
$endsubnet = "$($endrange.Split(".")[0]).$($endrange.Split(".")[1]).$($endrange.Split(".")[2])."
if ($startsubnet -eq $endsubnet) {
    $startip = $($startrange.Split(".")[3])
    $endip = $($endrange.Split(".")[3])
    $startip..$endip | foreach{
        $lastoctet = $_
        try {
            Test-Connection -ComputerName $startsubnet$lastoctet -Count 1 -ErrorAction Stop |
             Select -ExpandProperty Address |
             foreach { [System.Net.Dns]::GetHostByAddress($_) }
        }
        catch [System.Net.NetworkInformation.PingException] {
            #Write-Host "Test-Connection failed for $startsubnet$lastoctet"
            $Prop = [Ordered]@{
                    'Hostname' = "*"
                    'Aliases' = @()
                    'AddressList' = @("$startsubnet$lastoctet")
                    }
            New-Object PsObject -Property $Prop
        }
        catch [System.Management.Automation.MethodInvocationException] {
            $Prop = [Ordered]@{
                    'Hostname' = "<UNKNOWN>"
                    'Aliases' = @()
                    'AddressList' = @("$startsubnet$lastoctet")
                    }
            New-Object PsObject -Property $Prop
        }
    }
} else {
    Write-Host "Start subnet was not the same as the end subnet"
}

Open in new window

0
 
LVL 1

Author Closing Comment

by:NAMEWITHELD12
ID: 40651253
thanks and sorry for the delay
0

Featured Post

Optimizing Cloud Backup for Low Bandwidth

With cloud storage prices going down a growing number of SMBs start to use it for backup storage. Unfortunately, business data volume rarely fits the average Internet speed. This article provides an overview of main Internet speed challenges and reveals backup best practices.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Are you one of those front-line IT Service Desk staff fielding calls, replying to emails, all-the-while working to resolve end-user technological nightmares? I am! That's why I have put together this brief overview of tools and techniques I use in o…
Set OWA language and time zone in Exchange for individuals, all users or per database.
Windows 8 came with a dramatically different user interface known as Metro. Notably missing from that interface was a Start button and Start Menu. Microsoft responded to negative user feedback of the Metro interface, bringing back the Start button a…
With the advent of Windows 10, Microsoft is pushing a Get Windows 10 icon into the notification area (system tray) of qualifying computers. There are many reasons for wanting to remove this icon. This two-part Experts Exchange video Micro Tutorial s…

864 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

24 Experts available now in Live!

Get 1:1 Help Now