Script to ping multiple hosts and return if the IP corresponds to the correct host

Jairon Junior 21 Reputation points
2022-01-12T17:34:20.107+00:00

Hey there, wonder if anyone can help me, I'm currently new to the area, so I really don't know much about it, i'm looking for a way to make my job easier, I'm currently needing to ping a lot of machines so when it's on I can run some tasks, the problem is that on the list I'm currently working on has a lot of duplicated dns machines, so the host returns as ON, but it's in fact other machine, would appreciate if while pinging the hosts it would do something like a (ping -a to the ip) so I would know for sure i'ts the correct host. Please forgive my confusing english, it's pretty rusty nowadays @_@.
The script i'm currently using is the following, if possible would be awesome if someone could add the function in it, thanks!!!

$Output= @()

$names = Get-Content ".\ip4.txt"

foreach ($name in $names){

if (Test-Connection -Delay 15 -ComputerName $name -Count 1 -ErrorAction SilentlyContinue){

$Output+= "$name"

Write-Host "$Name" -ForegroundColor Green

}

else{

$Output+= "$name"

Write-Host "$Name" -ForegroundColor Red

}

}

$Output | Out-file ".\result.csv"

Windows for business Windows Server User experience PowerShell
0 comments No comments
{count} votes

Accepted answer
  1. Rich Matheisen 47,901 Reputation points
    2022-01-12T21:13:15.07+00:00

    See if this works for you:

    Get-Content ".\ip4.txt" |
        ForEach-Object{
            $result = [ordered]@{
                        DNSName     = $_.Trim()
                        HostName    = ""
                        DNSIPv4     = ""
                        Up          = ""
                        TestedIPv4  = ""
                        }
            Try{
                $entry = [System.Net.Dns]::GetHostEntry($_.Trim())
                $result.HostName = $entry.HostName
                $entry.AddressList |
                    Where-Object {$_.AddressFamily -eq 'InterNetwork'} |
                        ForEach-Object{
                            $result.DNSIPv4 = $_.IPAddressToString
                            [array]$x = Test-Connection -Delay 15 -ComputerName $result.DNSName -Count 1 -ErrorAction SilentlyContinue
                            if ($x){
                                $result.Up = "Yes"
                                $result.TestedIPv4 = $x[0].IPV4Address
                            }
                            else{
                                $result.Up = "No"
                                $result.TestedIPv4 = "N/A"
                            }
                        }
            }
            Catch{
                $result.HostName = "Host Unknown"
                $result.Up = "Unknown"
                $result.TestedIPv4 = "N/A"
            }
            [PSCustomObject]$result
        }
    

    You can pipe the results to Export-Csv or Format-Table. There's no red or green, but you can get what you need from a CSV and select or sort as you like.

    1 person found this answer helpful.

4 additional answers

Sort by: Most helpful
  1. Michael Taylor 60,161 Reputation points
    2022-01-12T19:13:13.19+00:00

    Well it seems like you are actually wanting to do 2 different things: a) ping to verify a machine is available, and b) get the DNS name that goes with the IP address you're pinging. Definitely doable with the ping command but parsing that output isn't my favorite option so I'd personally break it up into 2 steps. Firstly I'd get the DNS name given the IP address (if any) and then I'd ping the machine to verify it is online. Perhaps something like this.

    $addresses = Get-Content ".\ip4.txt"
    foreach ($address in $addresses) {
       $entry = [System.Net.Dns]::GetHostEntry($address)
       if ($entry -and Test-Connection -delay 15 -computername $entry.HostName -count 1 -ErrorAction SilentlyContinue) {
          $Output += $entry.HostName
       }
    }
    

    HostName has the DNS name as defined by the DNS resolution.


  2. Rich Matheisen 47,901 Reputation points
    2022-01-13T20:21:21.42+00:00

    You have quite a problem to solve! This won't fix the problem of orphaned resource records but it might buy you some time. It will keep all singleton "A" records, and it will remove all but the MOST RECENT resource record type (currently set to "A") based on the timestamp. It ignores all records that are static (i.e. have no timestamp).

    NOTE: I HAVE NOT TESTED THIS AT ALL.
    I do have a "-WhatIf" on the Remove-DnsServerResourceRecord, but still use caution and TEST

    $zonename = "your.dns.zone.name.goes.here"  
    $recordtype = "A"  
    $SpecialNames = "DomainDnsZones", "ForestDnsZones", "@"  
    $RR = Get-DnsServerResourceRecord -ZoneName $zonename |  
                    Where-Object {$_.RecordType -eq $recordtype -and $null -ne $_.TimeStamp -and $SpecialNames -notcontains $_.HostName} |  
                        Sort-Object -Property   @{Expression="HostName";Descending=$false},  
                                                @{Expression="TimeStamp";Descending=$true}  
      
    $RR | Export-CSV C:\junk\$zonename.csv -NoTypeInformation   # just for recordkeeping!  
      
    $currenthost = ""  
    ForEach ($host in $RR) {  
        if ($currenthost -eq ""){  
            $currenthost = $host.HostName  
            continue  
        }  
        if ($host.HostName -eq $currenthost){   # duplicate  
            Remove-DnsServerResourceRecord -ZoneName $zonename -RRType $recordtype -Name $host.HostName -RecordData $host.recorddata.ipv4address.ipaddresstostring -WHATIF  
            continue  
        }  
        $currenthost = $host.HostName   # use this hostname to compare agains next hostname  
    }  
    
    
    
      
    

  3. Eric Orosz 66 Reputation points
    2022-08-19T19:16:11.673+00:00

    Where in the script would I add the Export-csv command to output the data of all the hostnames from the text file.

     Get-Content "C:TEMP\Servers and DCs.txt" |  
         ForEach-Object{  
             $result = [ordered]@{  
                         DNSName     = $_.Trim()  
                         HostName    = ""  
                         DNSIPv4     = ""  
                         Up          = ""  
                         TestedIPv4  = ""  
                         }  
             Try{  
                 $entry = [System.Net.Dns]::GetHostEntry($_.Trim())  
                 $result.HostName = $entry.HostName  
                 $entry.AddressList |  
                     Where-Object {$_.AddressFamily -eq 'InterNetwork'} |  
                         ForEach-Object{  
                             $result.DNSIPv4 = $_.IPAddressToString  
                             [array]$x = Test-Connection -Delay 15 -ComputerName $result.DNSName -Count 1 -ErrorAction SilentlyContinue  
                             if ($x){  
                                 $result.Up = "Yes"  
                                 $result.TestedIPv4 = $x[0].IPV4Address  
                             }  
                             else{  
                                 $result.Up = "No"  
                                 $result.TestedIPv4 = "N/A"  
                             }  
                         }  
             }  
             Catch{  
                 $result.HostName = "Host Unknown"  
                 $result.Up = "Unknown"  
                 $result.TestedIPv4 = "N/A"   
             }  
             [PSCustomObject]$result | Export-Csv -Path "C:\Temp\Servers&DC_DNS_Results.csv" -NoTypeInformation  
         }  
           
    
    0 comments No comments

  4. Rich Matheisen 47,901 Reputation points
    2022-01-14T19:47:56.303+00:00

    Here's the problem: When you "ping" by IP address, the name of the host is retrieved from DNS by asking the server for the PTR record(s). In other words, it does a "reverse lookup", like getting a person's name by looking up their telephone number. So what happens if there are not only multiple "A" records for the host name (with different IP addresses), but also multiple "PTR" records for the IP address (with different host names)?

    I don't know that your DNS lookups are deterministic. Can you rely on getting the answers to every query in the same order if there are multiple records that satisfy the query?

    Right now I don't think you can rely on getting the answers you need from DNS, at least not without a lot more scripting.

    However, you can try getting the name of the machine that's using an IP address right from the horse's mouth, so to speak, by asking the IP address's owner.

    See if this helps:

    Get-Content ".\ip4.txt" |
        ForEach-Object {
            $result = [ordered]@{
                DNSName           = $_.Trim()
                HostName          = ""
                DNSIPv4           = ""
                Up                = ""
                TestedIPv4        = ""
                AnsweringHostName = ""
                HostNamesMatch    = ""
            }
            Try {
                $entry = [System.Net.Dns]::GetHostEntry($_.Trim())
                $result.HostName = $entry.HostName
                $entry.AddressList |
                    Where-Object { $_.AddressFamily -eq 'InterNetwork' } |
                        ForEach-Object {
                            $result.DNSIPv4 = $_.IPAddressToString
                            $result.AnsweringHostName = (Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName $_.IPAddressToString).Name
                            $result.HostNamesMatch = $false
                            if ($result.AnsweringHostName -eq $result.HostName) {
                                $result.HostNamesMatch = $true
                            }
                            [array]$x = Test-Connection -Delay 15 -ComputerName $result.DNSName -Count 1 -ErrorAction SilentlyContinue
                            if ($x) {
                                $result.Up = "Yes"
                                $result.TestedIPv4 = $x[0].IPV4Address
                            }
                            else {
                                $result.Up = "No"
                                $result.TestedIPv4 = "N/A"
                            }
                        }
            }
            Catch {
                $result.HostName = "Host Unknown"
                $result.Up = "Unknown"
                $result.TestedIPv4 = "N/A"
            }
            [PSCustomObject]$result
        }
    

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.