Check for Available IP's on a network

One of the monotonous tasks I run into frequently while building servers is having to find available IP’s for the servers. Typically I need to login to our IPAM and find what’s available depending on the vLAN and even then I usually ping an IP to confirm it’s not being used.

To help with this task I wrote script that does most of the heavy lifting for me.
let’s say you are building a new server on a specific vLAN where the IP is something like 10.111.22.*.

When you run the script it will ask you to type in the IP. It doesn’t really matter what IP you type in because it strips out the last octet and uses the ful IP range to scan for what’s available. In the scenario above it would scan 10.111.22.1 - 10.111.22.254.

The script itself is very fast and returns available IP’s in that range in under 1 second. You can obviously use this concept in other scripts, but it’s always a good idea to double check your work to make sure you don’t get any false positives/negatives.

Also, credit goes to Boe Prox for original concept.
Here is the script:

CLS

#SRC: https://github.com/proxb/AsyncFunctions/blob/master/Test-ConnectionAsync.ps1

Clear-Variable Result, Task, Object -Force -Confirm:$False -ErrorAction SilentlyContinue

#===================

#Set Variables

#Ask user for an IP
Do
{
    CLS
    $IP = Read-Host "Type in an IP"

}until($IP -match "^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$" -and [bool]($IP -as [ipaddress]))

$IPRange = 1..254 | % {"$($IP.Substring(0, $IP.lastIndexOf('.'))).$_"}

#===================

$Task = ForEach ($IP in $IPRange) 
{
    [pscustomobject] @{
        IP = $IP
        Task = (New-Object System.Net.NetworkInformation.Ping).SendPingAsync($IP,100)
    }
}        

Try 
{
    [void][Threading.Tasks.Task]::WaitAll($Task.Task)
} 
Catch {}

$Task | ForEach {
    If ($_.Task.IsFaulted) 
    {
        $Result = $_.Task.Exception.InnerException.InnerException.Message
        $IPAddress = $Null
    } 
    Else 
    {
        $Result = $_.Task.Result.Status
        $IPAddress = $_.task.Result.Address.ToString()
    }

    $Object = [pscustomobject]@{
        IP = $_.IP
        IPAddress = $IPAddress
        Result = $Result
    }

    $Object.pstypenames.insert(0,'Net.AsyncPingResult')
    $Object | Where-Object { ($_.Result -ne "Success") } | Select-Object -Property IP -ExpandProperty IP
}