Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

Test Port 2.0

Posted on May 31, 2011

A few years ago I updated a PowerShell script I came across to scan a computer for open ports. My initial revision was aimed at making it more pipeline friendly in PowerShell v1.0. I recently needed to use the function for a project and realized it could benefit from a 2.0 upgrade.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!

The new function uses a valid verb in the name, "Test", as opposed to the old "Scan". I was also able to take advantage of cmdletbinding, New-Object and Try/Catch. Not to mention comment based help, which is in the download file.

[cc lang="PowerShell"]
Function Test-Port {

[cmdletbinding(SupportsShouldProcess=$True,ConfirmImpact="Low")]

Param(
[Parameter(Position=0,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
[ValidateNotNullorEmpty()]
[string[]]$Computername=$env:computername,
[array]$Ports=@("21","22","23","25","80","443","3389")
)

Begin {
#set values for Write-Progress
Write-Verbose "$(Get-Date) Starting $($myinvocation.mycommand)"
Write-Verbose "$(Get-Date) Scannning for ports $($ports -as [string])"
$activity="Port Scan"
}

Process {

Foreach ($computer in $computername) {

#whatif
if ($pscmdlet.ShouldProcess($($computer.ToUpper()))) {
$status="Scanning $computer"
Write-Verbose "$(Get-Date) $status"
$i=0

foreach ($port in $ports) {
$i++
Write-Progress -Activity $activity -status $status `
-currentoperation "port $port" -percentcomplete (($i/$ports.count)*100)

Try {
#create the TCPClient object
$tcp=New-Object System.Net.Sockets.TcpClient($computer, $port) -ErrorAction Stop
}
Catch {
Write-Verbose "$(Get-Date) Connection refused"
}
if ($tcp.client.connected)
{
[string]$rep=$tcp.client.RemoteEndPoint
[string]$ip=$rep.substring(0,$rep.indexof(":"))

$PortOpen=$True
$TTL=$($tcp.client.ttl)
$RemoteIP=$ip

}
else
{
Write-Verbose "$(Get-Date) $($computer.ToUpper()) not open on port: $port"
$PortOpen=$False
$TTL=-1
$RemoteIP=$Null
} #end Else

#disconnect the socket connection if open
if ($PortOpen)
{
Write-Verbose "$(Get-Date) Disconnecting from $($computer.ToUpper())"
$tcp.client.disconnect($False)
}

#write a custom object to the pipeline
New-Object -TypeName PSObject -Property @{
Computername=$Computer.ToUpper()
Port=$Port
Open=$PortOpen
TTL=$TTL
RemoteIP=$RemoteIP

}

} #end foreach $port

#dispose and disconnect
if ($tcp)
{
$tcp.close()
}
} #if shouldprocess
} #foreach $computer
} #end process

End {
Write-Progress -Activity $activity -status "Complete" -Completed
Write-Verbose "$(Get-Date) Ending $($myinvocation.mycommand)"
}#end

} #end function
[/cc]

The function supports -Whatif and -Confirm since scanning ports could be time consuming and something you may want to verify before you start scanning a large number of computers. You can pipe computer names to the function but the function will scan the same array of ports. The default array is 21, 22,23,25,80,443 and 3389. These are TCP ports by the way.

The function uses the .NET System.Net.Sockets.TcpClient class to open the port on the coimputer.

[cc lang="PowerShell"]
Try {
#create the TCPClient object
$tcp=New-Object System.Net.Sockets.TcpClient($computer, $port) -ErrorAction Stop
}
[/cc]

If the connection is made, the function retrieves some information and writes a custom object to the pipeline.

[cc lang="Powershell"]
#write a custom object to the pipeline
New-Object -TypeName PSObject -Property @{
Computername=$Computer.ToUpper()
Port=$Port
Open=$PortOpen
TTL=$TTL
RemoteIP=$RemoteIP
}
[/cc]

Because the function takes advantage of the pipeline, you can run an expression like this:

[cc lang="DOS"]
PS C:\> get-content computers.txt | Test-Port -port 80 | Where {$_.Open} | Out-File Open80.txt
[/cc]

This one line command will test all the computers listed in computer.txt for port 80 and save the results where true to Open80.txt. The function uses Write-Progress to provide feedback on what is being scanned. Write-Progress is not used as often as it could be and I think it's because there aren't enough practical examples, so I'm hoping this will help.

Enjoy and let me know what you think.

Download Test-Port.


Behind the PowerShell Pipeline

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

2 thoughts on “Test Port 2.0”

  1. Alan renouf says:
    May 31, 2011 at 9:40 am

    awesome stuff, now I don’t need to install telnet every time I want to check a port !

    1. Jeffery Hicks says:
      May 31, 2011 at 9:41 am

      Exactly. And I had PowerCLI in mind when I wrote it.

Comments are closed.

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d