I've wrote a powershell script which I would like to share.
I use this script to scan network range for active hosts and resolve them.
I use background jobs for faster execution.
I would like to know how I can more optimize this regarding performance etc.
Any feedback is welcome.
function Test-IP-Range
{
param($range)
$proceed = $true
$split = $range.split(".")
if ($split.count -eq 4)
{
0..3 | foreach{
if ($split[$_] -lt 1 -and $split[$_] -gt 254) {$proceed = $false}
}
}
else {$proceed = $false}
$concurrent = 30
$amount_scans = 5
$sleepms = 500
$check = $amount_scans
$ActiveHosts = 0
$sw = new-object system.diagnostics.stopwatch
$sb=
{
param ($address,$amount_scans) #192.168.160.10
$split = $address.split(".")
$begin = $split[3] - ($amount_scans - 1)
$end = $split[3]
$go = @{}
$ping = new-object System.Net.NetworkInformation.Ping
for ($i = $begin; $i -ile $end; $i++)
{
$IP = $split[0] + "." + $split[1] + "." + $split[2] + "." + $i
$hash = "{0:D3}" -f $i
$go[$hash] += $ping.send($IP)
}
$go
}
if ($proceed)
{
Write-Host "Scanning $range is started" -ForegroundColor Red
$sw.start()
$range = $split[0] + "." + $split[1] + "." + $split[2] + "."
for ($i = 1; $i -ile 254; $i++)
{
if ($i % $amount_scans) { continue; }
$IP = $range + $i
$name = "SCAN_" + "{0:D3}" -f $i
$job_start = $true
while ($job_start)
{
$count = Get-Job | ? {$_.Name -match "SCAN" -and $_.State -eq "Running"}
$count_total = $count.count
if ($count -eq $null)
{
start-job -ScriptBlock $sb -name $name -ArgumentList $IP, $amount_scans | Out-Null
$job_start = $false
}
else
{
if ($count_total -lt $concurrent)
{
start-job -ScriptBlock $sb -name $name -ArgumentList $IP, $amount_scans | Out-Null
$job_start = $false
}
}
Start-Sleep -Milliseconds $sleepms
}
Get-Job | Sort Name | % {
$checkname = "SCAN_" + "{0:D3}" -f $check
if ($_.Name -eq $checkname -and $_.State -eq "Completed")
{
$Result = Receive-Job -Name $checkname
Remove-Job -Name $checkname -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
$ResultSorted = $Result.getenumerator() | sort-object -property key
foreach ($Record in $ResultSorted)
{
if ($Record.Value.Status -eq "Success")
{
$Address = $Record.Value.Address.IPAddressToString
try
{
$Resolve = [System.Net.DNS]::GetHostByAddress($Address)
$Hostname = $Resolve.HostName
}
catch {$Hostname = "Could not be resolved"}
$ActiveHosts++
Write-Host "$Address | $Hostname" -ForegroundColor "Green"
}
}
$check = $check + $amount_scans
}
}
}
#Scan last ip addresses
$split = $IP.split(".")
if ($split[3] -lt 254)
{
$name = "SCAN_" + "254"
$IP = $range + "254"
$amount = 254 - $split[3]
start-job -ScriptBlock $sb -name $name -ArgumentList $IP, $amount | Out-Null
}
#Handle remaining jobs
while ($proceed)
{
$checkname = "SCAN_" + "{0:D3}" -f $check
$Job = Get-Job | ? {$_.Name -eq $checkname -and $_.State -eq "completed"}
if ($Job -ne $null)
{
$Result = Receive-Job -Name $checkname
Remove-Job -Name $checkname -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
$ResultSorted = $Result.getenumerator() | sort-object -property key
foreach ($Record in $ResultSorted)
{
if ($Record.Value.Status -eq "Success")
{
$Address = $Record.Value.Address.IPAddressToString
try
{
$Resolve = [System.Net.DNS]::GetHostByAddress($Address)
$Hostname = $Resolve.HostName
}
catch {$Hostname = "Could not be resolved"}
$ActiveHosts++
Write-Host "$Address | $Hostname" -ForegroundColor "Green"
}
}
if ($check -lt 254 - $amount_scans) {
$check = $check + $amount_scans
}
else
{
if ($check -eq $split[3]){$check = 254}
else {$proceed = $false}
}
}
Start-Sleep -Milliseconds 200
}
Write-Host "$ActiveHosts Acitve Hosts Scanned" -ForegroundColor Red
$min = $sw.elapsed.minutes
$sec = $sw.elapsed.seconds
$sw.stop() | Out-Null
Write-Host "Duration: $min Min $sec Sec" -ForegroundColor Red
}
}
Test-IP-Range 192.168.250.0