Monday, February 15, 2016

Everyday Powershell - Part 37 - Powershell Subnet Scanner

So we had a need to run a subnet scan this morning on a host where installing a subnet scanner would be a hassle. So powershell to the rescue!

Turns out there's a really easy but slow way to do this...
1..254 | ForEach-Object {test-connection ("192.168.6." + $_)}
Then there's a tricky way that's much quicker.
function start-subnetscan{
    param(
        $addressspace = "192.168.6.",
        $startip = 1,
        $endip = 254,
        $concurrentthreads = 30
    )
    $report = @()
    $startip..$endip | ForEach-Object {
        Write-Progress -Activity "Pinging Computers" -Status ("Pinging " + $addressspace + $_.tostring().padleft(3,"0"+ " Starting Jobs. Started " + (get-job).count) -PercentComplete (($_ / $endip* 100)
        start-job -scriptblock {
            $temp = "" | select IP, Online
            $temp.ip = ($args[0] + $args[1].tostring().padleft(3,"0"))
            $temp.online = test-connection $temp.ip -Quiet -Count 1
            $temp
        } -ArgumentList $addressspace, $_  
        while((get-job).count -ge $concurrentthreads){
            Write-Progress -Activity "Pinging Computers" -Status ("Waiting for resources. " + (get-job).count + " jobs running"-PercentComplete (($_ / $endip* 100)
            $report += Get-Job | where state -eq 'completed' | Receive-Job
            Get-job | where state -eq 'completed' | Remove-Job
        }                           
    }
    $report += get-job | wait-job | Receive-Job
    $report | select IP, Online | sort IP | ft
    Get-job | wait-job  | Remove-Job
}

So to give you an idea of the power of multi threading we setup both commands so we could run them through measure-command and then we raced them!
Measure-Command -Expression {start-subnetscan} 
Days              : 0
Hours             : 0
Minutes           : 2
Seconds           : 55
Milliseconds      : 951
Ticks             : 1759513835
TotalDays         : 0.00203647434606481
TotalHours        : 0.0488753843055556
TotalMinutes      : 2.93252305833333
TotalSeconds      : 175.9513835
TotalMilliseconds : 175951.3835

Measure-Command -Expression {1..254 | ForEach-Object {test-connection ("192.168.6." + $_) -count 1}} 
Days              : 0
Hours             : 0
Minutes           : 11
Seconds           : 26
Milliseconds      : 940
Ticks             : 6869401183
TotalDays         : 0.00795069581365741
TotalHours        : 0.190816699527778
TotalMinutes      : 11.4490019716667
TotalSeconds      : 686.9401183
TotalMilliseconds : 686940.1183
 
Have a look at that! Running it multi-threaded made it 3 times faster.

No comments:

Post a Comment