88
99<#
1010 . SYNOPSIS
11+ Powerful asynchronus Port-Scanner which returns a custom PowerShell-Object with basic informations about the
12+ scanned Port-Range include Port and Status.
1113
1214 . DESCRIPTION
15+ This is a powerful asynchronus Port-Scanner working with the PowerShell RunspacePool. You can scan any
16+ Port-Range you want.
17+
18+ This script also work fine along with my asychronus IP-Scanner published on GitHub too. You can easily
19+ pipe the output of the IP-Scanner result in this script.
20+
21+ If you found a bug or have some ideas to improve this script... Let me know. You find my Github profile in
22+ the links below.
1323
1424 . EXAMPLE
25+ .\ScanPortsAsync.ps1 -IPv4Address 172.16.0.1 -StartPort 1 -EndPort 1000
26+
27+ . EXAMPLE
28+ .\ScanPortsAsync.ps1 -IPv4Address 192.168.1.100 -IncludeClosed
1529
1630 . LINK
1731 Github Profil: https://github.com/BornToBeRoot
@@ -23,20 +37,32 @@ Param(
2337 [Parameter (
2438 Position = 0 ,
2539 Mandatory = $true ,
26- HeldMessage = ' Enter IP-Address of the device which you want to scan' )]
40+ HelpMessage = ' Enter IP-Address of the device which you want to scan' )]
2741 [IPAddress ]$IPv4Address ,
2842
2943 [Parameter (
3044 Position = 1 ,
3145 Mandatory = $false ,
32- HelpMessage = ' ' )]
46+ HelpMessage = ' Enter the Start-Port (Default=1) ' )]
3347 [Int32 ]$StartPort = 1 ,
3448
3549 [Parameter (
3650 Position = 2 ,
3751 Mandatory = $false ,
38- HelpMessage = ' Enter the Start Port' )]
39- [Int32 ]$EndPort = 65535
52+ HelpMessage = ' Enter the End-Port (Default=65535)' )]
53+ [Int32 ]$EndPort = 65535 ,
54+
55+ [Parameter (
56+ Position = 3 ,
57+ Mandatory = $false ,
58+ HelpMessage = ' Set the maximum number of threads at the same time (Default=100)' )]
59+ [Int32 ]$Threads = 100 ,
60+
61+ [Parameter (
62+ Position = 4 ,
63+ Mandatory = $false ,
64+ HelpMessage = ' Show closed Ports in result' )]
65+ [Switch ]$IncludeClosed
4066)
4167
4268Begin {
@@ -49,20 +75,122 @@ Begin{
4975 # Validate Port-Range
5076 if ($StartPort -gt $EndPort )
5177 {
52-
78+ Write-Host " Check your input! Invalid Port-Range... (-StartPort can't be lower than -EndPort)" - ForegroundColor Red
79+ exit
5380 }
5481
55- # Some User-Output about the selected or default settings
82+ $PortRange = ($EndPort - $StartPort )
83+
84+ if (-not ( Test-Connection - ComputerName $IPv4Address - Count 2 - Quiet))
85+ {
86+ Write-Host " IP-Address not reachable!" - ForegroundColor Red
87+ exit
88+ }
5689
90+ # Some User-Output about the selected or default settings
91+ Write-Host " `n Script ($ScriptFileName ) started at $StartTime " - ForegroundColor Green
92+ Write-Host " `n +---------------------------------------Settings----------------------------------------`n |"
93+ Write-Host " | IP-Address:`t $IPv4Address "
94+ Write-Host " | Port-Range:`t $StartPort -$EndPort "
95+ Write-Host " | Threads:`t`t $Threads "
96+ Write-Host " |`n +---------------------------------------------------------------------------------------`n "
5797}
5898
5999Process {
100+ # Scriptblock that will run in runspaces (threads)...
101+ [System.Management.Automation.ScriptBlock ]$ScriptBlock = {
102+ # Parameters
103+ $IPv4Address = $args [0 ]
104+ $Port = $args [1 ]
105+
106+ try {
107+ $Socket = New-Object System.Net.Sockets.TcpClient($IPv4Address , $Port )
108+
109+ if ($Socket.Connected )
110+ {
111+ $Status = " Open"
112+ $Socket.Close ()
113+ }
114+ }
115+ catch
116+ {
117+ $Status = " Closed"
118+ }
119+
120+ $Result = New-Object - TypeName PSObject
121+ Add-Member - InputObject $Result - MemberType NoteProperty - Name Port - Value $Port
122+ Add-Member - InputObject $Result - MemberType NoteProperty - Name Status - Value $Status
123+ return $Result
124+ }
60125
126+ # Setting up runspaces
127+ Write-Host " Setting up Runspace-Pool...`t`t " - ForegroundColor Yellow - NoNewline
128+
129+ $RunspacePool = [System.Management.Automation.Runspaces.RunspaceFactory ]::CreateRunspacePool(1 , $Threads , $Host )
130+ $RunspacePool.Open ()
131+ $Jobs = @ ()
132+
133+ Write-Host " [" - ForegroundColor Gray - NoNewline; Write-Host " Done" - ForegroundColor Green - NoNewline; Write-Host " ]" - ForegroundColor Gray
61134
62- }
135+ # Setting up jobs
136+ Write-Host " Setting up jobs...`t`t`t " - ForegroundColor Yellow - NoNewline
63137
138+ foreach ($Port in $StartPort .. $EndPort )
139+ {
140+ if ($PortRange -gt 0 ) { $Progress_Percent = (($Port - $StartPort ) / $PortRange ) * 100 } else { $Progress_Percent = 100 }
141+ Write-Progress - Activity " Setting up jobs..." - Id 1 - Status " Current Port: $Port " - PercentComplete ($Progress_Percent )
142+
143+ $Job = [System.Management.Automation.PowerShell ]::Create().AddScript($ScriptBlock ).AddArgument($IPv4Address ).AddArgument($Port )
144+ $Job.RunspacePool = $RunspacePool
145+ $Jobs += New-Object psobject - Property @ {
146+ RunNum = $Port - $StartPort
147+ Pipe = $Job
148+ Result = $Job.BeginInvoke ()
149+ }
150+ }
64151
65- End {
152+ Write-Host " [" - ForegroundColor Gray - NoNewline; Write-Host " Done" - ForegroundColor Green - NoNewline; Write-Host " ]" - ForegroundColor Gray
153+
154+ # Wait until all Jobs are finished
155+ Write-Host " Waiting for jobs to complete...`t`t " - ForegroundColor Yellow - NoNewline
156+
157+ Do {
158+ Start-Sleep - Milliseconds 500
159+
160+ Write-Progress - Activity " Waiting for jobs to complete... ($ ( $Threads - $ ($RunspacePool.GetAvailableRunspaces ())) of $Threads threads running)" - Id 1 - PercentComplete (($Jobs.Count - $ ($ ($Jobs | Where-Object {$_.Result.IsCompleted -eq $false }).Count)) / $Jobs.Count * 100 ) - Status " $ ( @ ($ ($Jobs | Where-Object {$_.Result.IsCompleted -eq $false })).Count) remaining..."
161+ } While ($Jobs.Result.IsCompleted -contains $false )
162+
163+ Write-Host " [" - ForegroundColor Gray - NoNewline; Write-Host " Done" - ForegroundColor Green - NoNewline; Write-Host " ]" - ForegroundColor Gray
164+
165+ Write-Host " Process results...`t`t`t " - ForegroundColor Yellow - NoNewline
66166
167+ # Built global array
168+ $Results = @ ()
67169
170+ # Get results and fill the array
171+ foreach ($Job in $Jobs )
172+ {
173+ $Results += $Job.Pipe.EndInvoke ($Job.Result )
174+ }
175+
176+ Write-Host " [" - ForegroundColor Gray - NoNewline; Write-Host " Done" - ForegroundColor Green - NoNewline; Write-Host " ]" - ForegroundColor Gray
177+ }
178+
179+
180+ End {
181+ $EndTime = Get-Date
182+
183+ $ExecutionTimeMinutes = (New-TimeSpan - Start $StartTime - End $EndTime ).Minutes
184+ $ExecutionTimeSeconds = (New-TimeSpan - Start $StartTime - End $EndTime ).Seconds
185+
186+ # Some User-Output with Device UP/Down and execution time
187+ Write-Host " `n +----------------------------------------Result-----------------------------------------`n |"
188+ Write-Host " | Ports Open:`t`t $ ( @ ($Results | Where-Object {($_.Status -eq " Open" )}).Count) "
189+ Write-Host " | Ports Closed:`t $ ( @ ($Results | Where-Object {($_.Status -eq " Closed" )}).Count) "
190+ Write-Host " |`n +---------------------------------------------------------------------------------------`n "
191+ Write-Host " Script duration:`t $ExecutionTimeMinutes Minutes $ExecutionTimeSeconds Seconds`n " - ForegroundColor Yellow
192+ Write-Host " Script ($ScriptFileName ) exit at $EndTime `n " - ForegroundColor Green
193+
194+ # Return custom psobject with Port status
195+ if ($IncludeClosed ) { return $Results } else { return $Results | Where-Object {$_.Status -eq " Open" } }
68196}
0 commit comments