You are free to review the examples below, or to use this script module, but this PowerShell nmap-like script module (PSnmap) that I wrote years later beats this script module hands down in just about every imaginable way (except for how well it's documented). It's orders of magnitude faster, uses less resources, and is overall a more polished product. Subnets can also be specified using CIDR notation in that new script.
With PowerShell version 5 came "Test-Port" as well, for single ports (but it is inferior in some ways to PSnmap):Test-Port -ComputerName 192.168.0.1 -Port 80
Test-Port does not appear to exist in PowerShell version 7 as of 2021-10-11 - on Linux. PSnmap works fine in PowerShell 7 on Linux.
I wrote a module called Get-PortState which produces custom PowerShell objects that can be assigned to a variable, sent to Format-Table for console display, exported to CSV, or whatever you might want to do with them. However, for the sake of convenience, there's an -ExportToCsv parameter that allows you to specify a CSV output file name directly when you run the Get-PortState command. You also have the data/objects from the last Get-PortState run available with the command Get-PortStateLast and can pass that to Export-Csv (or ConvertTo-Csv and Set-Content).
One thing I noticed in my lab environment, is that the timeout for closed and filtered ports against some computers seems to be pretty long. Due to this, I added an -AsJob parameter and a -Timeout parameter (default of 3000 ms / 3 seconds if omitted; only in use together with -AsJob). This will speed up processing in many scenarios, but at the expense of using more resources as it spawns a powershell.exe process for each port connection attempt.Just as I was about to release the module, I thought it'd be nice to have a DNS lookup feature, and tried to implement this sanely and flexibly. If you pass in an IP that resolves to a host name, you will get the host name; if you pass in a host name that resolves to one or more IP addresses, you will get the IP address(es) - joined together with semicolons if there are more than one.
If you can't install modules (even for your user only), I made sure you can dot-source the script, as demonstrated in the below screenshot example.The old script I initially put up is still available at the bottom of this article, in case someone wants it, but I do recommend getting the new one. The old one only works against a single target host and is mostly a telnet replacement for checking for open ports a bit more gracefully, as I mention there. The newer script does that, and more, and is more consistent with recommended PowerShell cmdlet design (but not 100%).
Let's start with a simple code example in case you want to roll your own:foreach ($Computer in $ComputerName) { foreach ($Port in $Ports) { # Create a Net.Sockets.TcpClient object to use for # checking for open TCP ports. $Socket = New-Object Net.Sockets.TcpClient # Suppress error messages $ErrorActionPreference = 'SilentlyContinue' # Try to connect $Socket.Connect($Computer, $Port) # Make error messages visible again $ErrorActionPreference = 'Continue' # Determine if we are connected. if ($Socket.Connected) { "${Computer}: Port $Port is open" $Socket.Close() } else { "${Computer}: Port $Port is closed or filtered" } # Apparently resetting the variable between iterations is necessary. $Socket.Dispose() $Socket = $null } }
To just check for an open port on a single host, you can use something like the code below. This also has the added bonus of using an asynchronous call with a specified timeout in milliseconds ("3000" here).
#$computer, $port = $args[0,1] # assign values to these $mysock = new-object net.sockets.tcpclient $IAsyncResult = [IAsyncResult] $mysock.BeginConnect($computer, $port, $null, $null) measure-command { $succ = $iasyncresult.AsyncWaitHandle.WaitOne(3000, $true) } | % totalseconds $succ $mysock.Connected #$mysock.Close() $mysock.Dispose()
To emulate "netstat" and show locally listening ports, established connections, and remote ports that one single, local server is connected to, you can use this code:
$NetworkProperties = [System.Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties()$TcpConnections = $NetworkProperties.GetActiveTcpConnections()
$TcpConnections | Format-Table -AutoSize State LocalEndPoint RemoteEndPoint ----- ------------- -------------- Established 127.0.0.1:49156 127.0.0.1:49157 Established 127.0.0.1:49157 127.0.0.1:49156 Established 127.0.0.1:49158 127.0.0.1:49159 Established 127.0.0.1:49159 127.0.0.1:49158$TcpConnections | Select -Exp LocalEndpoint -First 3 | ft -AutoSize
AddressFamily Address Port ------------- ------- ---- InterNetwork 127.0.0.1 49156 InterNetwork 127.0.0.1 49157 InterNetwork 127.0.0.1 49158
But you probably do want PSnmap instead. It's so much better, and so much faster. Just have a look at that screenshot example.
'''NB!''' ''If you use the variable name $Data and dot-source the module/script rather than using it as a module, Get-PortStateLast will fail as the variable names collide. I'm using $Data in the script (I probably should change the variable name). The variable $Properties is also used.''
However, if you use it as a module and import it with the Import-Module command, the variables will be correctly scoped to the module, and you won't have this issue.-ComputerName | Required |
-Port | Required |
-ExportToCsv | Optional. Create a CSV report and save it to the specified file name, using UTF-8 encoding. The file will be overwritten without you being prompted, if it exists. |
-Timeout | Optional. Timeout in milliseconds before the script considers a port closed. Default 3000 ms (3 seconds). For speeding things up. Only in effect when used with the -AsJob parameter. |
-AsJob | Optional. Use one job for each port connection attempt. This allows you to override the possibly lengthy timeout from the connecting socket, and a port is considered closed if we haven't been able to connect within the allowed time. Default 3000 ms. See the -Timeout parameter. This may be quite resource-consuming! Ports that are determined to be closed via timeout will be tagged with a "(t)" for timeout. |
-Dns | Optional. Try to determine IP if given a host name or host name if given an IP. Multiple values are joined with semicolons: ";". |
-NoPing | Optional. Do not try to ping the target computer if this is specified. By default, the script skips the port checks on targets that do not respond to ICMP ping and populate the fields with hyphens for these hosts. Be aware that computers that do not resolve via DNS/WINS/NetBIOS will also be reported as having failed the ping check. |
-ContinueOnPingFail | Optional. Try to check the target computer for open ports even if it does not respond to ping. Be aware that computers that do not resolve via DNS/WINS/NetBIOS will also be processed like this (and it should report them as "closed"). |
-Quiet | Optional. Do not display results with Write-Host directly as the script progresses. |
-NoSummary | Optional. Do not display a summary at the end. The summary includes start and end time of the script, and the output file name, if -ExportToCsv was specified. |
PS C:\PowerShell> Import-Module Get-PortState PS C:\PowerShell> Get-PortState -comp 2008r2esxi -Port 3389,80 -Dns -Quiet Start time: 07/29/2012 10:51:14 End time: 07/29/2012 10:51:14 ComputerName : 2008r2esxi Ping : Yes IP/DNS : 192.168.1.131 Port 80 : Open Port 3389 : OpenPS C:\PowerShell> Get-PortStateLast | ft -a
ComputerName Ping IP/DNS Port 80 Port 3389 ------------ ---- ------ ------- --------- 2008r2esxi Yes 192.168.1.131 Open Open
To also suppress the summary, use the -NoSummary parameter along with -Quiet. Here I also pipe to Format-Table -Autosize (ft -a) for a neater display of the information.
PS C:\PowerShell> Import-Module Get-PortState PS C:\PowerShell> Get-PortState -comp 2008r2esxi -Port 3389,80 -Dns -Quiet -NoSummary | ft -a ComputerName Ping IP/DNS Port 80 Port 3389 ------------ ---- ------ ------- --------- 2008r2esxi Yes 192.168.1.131 Open Open
PS C:\PowerShell> Import-Module Get-PortState PS C:\PowerShell> Get-PortState -Comp 192.168.1.131,vista64esxi,ubuntu64esxi,192.168.1.153 -Port 80,22,3389,445,20000 -AsJob -Dns -quiet | ft -a Start time: 07/29/2012 11:16:08 End time: 07/29/2012 11:17:03 ComputerName Ping IP/DNS Port 22 Port 80 Port 445 Port 3389 Port 20000 ------------ ---- ------ ------- ------- -------- --------- ---------- 192.168.1.131 Yes 2008r2esxi.svendsen.local Closed (t) Open Open Open Closed (t) 192.168.1.153 Yes 192.168.1.153 Open Closed (t) Closed (t) Closed (t) Closed (t) ubuntu64esxi Yes 192.168.1.102 Open Open Open Closed Closed vista64esxi Yes 192.168.1.172 Closed (t) Closed (t) Open Open Closed (t) PS C:\PowerShell> # I wanted a CSV file and don't want to start over. Now what? PS C:\PowerShell> Get-PortStateLast | Export-Csv -NoType -Enc utf8 port-report.csv PS C:\PowerShell> Import-Csv .\port-report.csv | ft -a ComputerName Ping IP/DNS Port 22 Port 80 Port 445 Port 3389 Port 20000 ------------ ---- ------ ------- ------- -------- --------- ---------- 192.168.1.131 Yes 2008r2esxi.svendsen.local Closed (t) Open Open Open Closed (t) 192.168.1.153 Yes 192.168.1.153 Open Closed (t) Closed (t) Closed (t) Closed (t) ubuntu64esxi Yes 192.168.1.102 Open Open Open Closed Closed vista64esxi Yes 192.168.1.172 Closed (t) Closed (t) Open Open Closed (t) PS C:\PowerShell> # voila
PS C:\> Import-Module Get-PortState PS C:\> Get-PortState -comp 2008r2esxi -port 3389 -Dns -quiet -nosum | ft -a ComputerName Ping IP/DNS Port 3389 ------------ ---- ------ --------- 2008r2esxi Yes fe80::b434:bc55:a730:d672%10;192.168.1.131 Open PS C:\> Get-PortStateLast | select -expand 'IP/DNS' | %{ $_ -split ';' } fe80::b434:bc55:a730:d672%10 192.168.1.131 PS C:\>
Something like this is the least you can get away with:
PS C:\> if ( (Get-PortState ubuntu64esxi 22 -nos -q).'Port 22' -eq 'Open' ) { 'Do stuff' } else { 'Do other stuff' } Do stuff PS C:\> if ( (Get-PortState ubuntu64esxi 23 -nos -q).'Port 23' -eq 'Open' ) { 'Do stuff' } else { 'Do other stuff' } Do other stuff
This PowerShell script checks for open ports, or an open port, using the .NET class Net.Sockets.TcpClient. Why didn't I think of this sooner? Essentially it's a replacement for using telnet for checking for open ports. I use this script now, rather than having to start a separate cmd window for each port to test with telnet, and then having the useless cursor in the top left corner, and usually having to close the window or wait for a timeout, if the port is open.
It works like this:
Download Check-Open-Ports.ps1.txt (right-click and "save as").
Powershell Windows Networking All CategoriesMinimum cookies is the standard setting. This website uses Google Analytics and Google Ads, and these products may set cookies. By continuing to use this website, you accept this.