How to check open ports using powershell? - powershell

I would like to write a script to check radom IP or hostname to see if ports are open. Here is what I have so far. The scripts name is checkports.
foreach ($xhost in $computername){
Write-Host $xhost
foreach ($port in $ports) {
$Socket = New-Object System.Net.Sockets.TCPClient
$Connection = $Socket.BeginConnect($xhost,$port,$null,$null)
$Connection.AsyncWaitHandle.WaitOne(5000,$false) | out-null
if ($Connection -eq $true)
{ write-host = "$xhost port $port is open" }
else
{ write-host = "port $port is closed" }
$Socket.EndConnect($Connection)
$Socket.Close()
}
}
I would like to input values in the following way:
.\checkport '192.186.1.5'
or
'192.168.1.5', '192.168.1.105', 192.168.1.110' | checkport
It doesn't seem to be reading IP address or displaying results.
I was wondering if anyone could point out there could show me what I am doing wrong in with this script?

I've been able to use the 'Test-Port' function from Boe Prox for similar scan/ reporting functions, the code is available on PoshCode:
http://poshcode.org/2514
When I needed to test ports for Directory health, I built a csv with 'port' and 'protocol' columns, then added the port number/ protocol for each port to check. This was used in the following script:
. .\test-port.ps1
$computersToCheck = get-content .\computers.txt
$portList = Import-CSV .\portList.csv
foreach($entry in $portList)
{
$testPortParams = #{
port = $($entry.port)
}
if( $($entry.protocol) -eq "tcp")
{ $testPortParams += #{ TCP = $true } }
else
{ $testPortParams += #{ UDP = $true } }
$outLog = "portTest-$($entry.port)-$($entry.protocol).txt"
$computersToCheck |
Test-Port #testPortParams |
Sort-Object -Property open,name -descending |
format-table -auto -outVariable status
Add-Content -path $outLog -value $status
}
You could certainly build a feeder script to build the range of IP addresses and ports to scan.

Related

PowerShell switch statement not working in TCP/UDP port scanner

I am a PowerShell newbie trying to make a TCP and UDP port scanner. My code has a switch statement, where if you press 1 and enter that goes to the TCP function, 2 and enter the UDP function, or Q to quit it.
The issue is that the switch doesn't work properly. If you press 1 for TCP that just gives you the syntax prompt and asks you to press enter, then just ends the script - the same for TCP option 2. The Q button to quit works fine.
Can someone help? I can't spot what is wrong. My code is below
Thank you
Write-Host "Port Scanner"
function Show-Menu
{
param (
[string]$Title = 'Options'
)
Clear-Host
Write-Host "================ $Title ================"
Write-Host "1: Press '1' for TCP."
Write-Host "2: Press '2' for UDP."
Write-Host "Q: Press 'Q' to quit."
}
do
{
Show-Menu
$selection = Read-Host "Make a selection"
switch ($selection)
{
'1' {
Write-Host "To scan for open ports, run the following command: scan-port [devicename] -ports"
Function Scan-Port {
Param([string]$computername=$env:computername,
[array]$ports=#("21","22","23","25","80","443","3389")
)
#turn off error pipeline
$ErrorActionPreference = "SilentlyContinue"
#set values for Write-Progress
$activity="Port Scan"
$status="Scanning $computername"
$i=0
foreach ($port in $ports){
$i++
Write-Progress -Activity $activity -status $status `
-currentoperation "port $port" -percentcomplete (($i/$ports.count)*100)
#create empty custom object
$obj=New-Object PSObject
$obj | Add-Member -MemberType Noteproperty -name "Computername" -value $computername.ToUpper()
$obj | Add-Member -MemberType Noteproperty -name "Port" -value $port
$tcp=New-Object System.Net.Sockets.TcpClient($computername, $port)
if ($tcp.client.connected) {
$obj | Add-Member -MemberType Noteproperty -name "PortOpen" -value $True
[string]$rep=$tcp.client.RemoteEndPoint
[string]$ip=$rep.substring(0,$rep.indexof(":"))
}
else {
# Write-Warning "$computername not open on port: $port"
$obj | Add-Member -MemberType Noteproperty -name "PortOpen" -value $False
} #end Else
write $obj
$obj | Export-Csv -Append -path '.\PortScanResults.csv' -Delimiter ";" -Force
#disconnect the socket connection
$tcp.client.disconnect($False)
} #end foreach
#dispose and disconnect
$tcp.close()
Write-Progress -Activity $activity -status "Complete" -Completed
} #end function
} '2' {
Function port-scan-udp {
param($hosts,$ports)
if (!$ports) {
Write-Host "usage: test-port-udp <host|hosts> <port|ports>"
Write-Host " e.g.: test-port-udp 192.168.1.2 445`n"
return
}
$out = ".\scanresults.txt"
foreach($p in [array]$ports) {
foreach($h in [array]$hosts) {
$x = (gc $out -EA SilentlyContinue | select-string "^$h,udp,$p,")
if ($x) {
gc $out | select-string "^$h,udp,$p,"
continue
}
$msg = "$h,udp,$p,"
$u = new-object system.net.sockets.udpclient
$u.Client.ReceiveTimeout = 500
$u.Connect($h,$p)
# Send a single byte 0x01
[void]$u.Send(1,1)
$l = new-object system.net.ipendpoint([system.net.ipaddress]::Any,0)
$r = "Filtered"
try {
if ($u.Receive([ref]$l)) {
# We have received some UDP data from the remote host in return
$r = "Open"
}
} catch {
if ($Error[0].ToString() -match "failed to respond") {
# We haven't received any UDP data from the remote host in return
# Let's see if we can ICMP ping the remote host
if ((Get-wmiobject win32_pingstatus -Filter "address = '$h' and Timeout=1000 and ResolveAddressNames=false").StatusCode -eq 0) {
# We can ping the remote host, so we can assume that ICMP is not
# filtered. And because we didn't receive ICMP port-unreachable before,
# we can assume that the remote UDP port is open
$r = "Open"
}
} elseif ($Error[0].ToString() -match "forcibly closed") {
# We have received ICMP port-unreachable, the UDP port is closed
$r = "Closed"
}
}
$u.Close()
$msg += $r
Write-Host "$msg"
echo $msg >>$out
}
}
}
}
}
pause
}
until ($selection -eq 'q')
I have another issue I am hoping you can help with. The TCP bit now works but the UDP scanner isn't accepting any paramaters. If I put in the syntax and then press Enter nothing happens. Thanks
} '2' {
Function portudp {
Param($hosts,$ports)
if (!$ports) {
Write-Host "usage: portudp <host|hosts> <port|ports>"
Write-Host " e.g.: portudp 192.168.1.2 445`n"
return
}
$out = ".\scanresults.txt"
foreach($p in [array]$ports) {
foreach($h in [array]$hosts) {
$x = (gc $out -EA SilentlyContinue | select-string "^$h,udp,$p,")
if ($x) {
gc $out | select-string "^$h,udp,$p,"
continue
}
$msg = "$h,udp,$p,"
$u = new-object system.net.sockets.udpclient
$u.Client.ReceiveTimeout = 500
$u.Connect($h,$p)
# Send a single byte 0x01
[void]$u.Send(1,1)
$l = new-object system.net.ipendpoint([system.net.ipaddress]::Any,0)
$r = "Filtered"
try {
if ($u.Receive([ref]$l)) {
# We have received some UDP data from the remote host in return
$r = "Open"
}
} catch {
if ($Error[0].ToString() -match "failed to respond") {
# We haven't received any UDP data from the remote host in return
# Let's see if we can ICMP ping the remote host
if ((Get-wmiobject win32_pingstatus -Filter "address = '$h' and Timeout=1000 and ResolveAddressNames=false").StatusCode -eq 0) {
# We can ping the remote host, so we can assume that ICMP is not
# filtered. And because we didn't receive ICMP port-unreachable before,
# we can assume that the remote UDP port is open
$r = "Open"
}
} elseif ($Error[0].ToString() -match "forcibly closed") {
# We have received ICMP port-unreachable, the UDP port is closed
$r = "Closed"
}
}
$u.Close()
$msg += $r
Write-Host "$msg"
echo $msg >>$out
$out | Export-Csv -Append -path '.\UDPPPortScanResults.csv' -Delimiter ";" -Force
}
}
}
portudp
}
}
pause
}
until ($selection -eq 'q')
UDP Function Output

How to ping continuously in the background in powershell?

This is my first program in powershell, Im trying to get from the user input and then pinging the IP address or the hostname, Creating text file on the desktop.
But if the user wants the add more than one IP I get into infinite loop.
Here Im asking for IP address.
$dirPath = "C:\Users\$env:UserName\Desktop"
function getUserInput()
{
$ipsArray = #()
$response = 'y'
while($response -ne 'n')
{
$choice = Read-Host '
======================================================================
======================================================================
Please enter HOSTNAME or IP Address, enter n to stop adding'
$ipsArray += $choice
$response = Read-Host 'Do you want to add more? (y\n)'
}
ForEach($ip in $ipsArray)
{
createFile($ip)
startPing($ip)
}
}
Then I creating the file for each IP address:
function createFile($ip)
{
$textPath = "$($dirPath)\$($ip).txt"
if(!(Test-Path -Path $textPath))
{
New-Item -Path $dirPath -Name "$ip.txt" -ItemType "file"
}
}
And now you can see the problem, Because I want the write with TIME format, I have problem with the ForEach loop, When I start to ping, And I cant reach the next element in the array until I stop
the cmd.exe.
function startPing($ip)
{
ping.exe $ip -t | foreach {"{0} - {1}" -f (Get-Date), $_
} >> $dirPath\$ip.txt
}
Maybe I should create other files ForEach IP address and pass params?
Here's a old script I have. You can watch a list of computers in a window.
# pinger.ps1
# example: pinger yahoo.com
# pinger c001,c002,c003
# $list = cat list.txt; pinger $list
param ($hostnames)
#$pingcmd = 'test-netconnection -port 515'
$pingcmd = 'test-connection'
$sleeptime = 1
$sawup = #{}
$sawdown = #{}
foreach ($hostname in $hostnames) {
$sawup[$hostname] = $false
$sawdown[$hostname] = $false
}
#$sawup = 0
#$sawdown = 0
while ($true) {
# if (invoke-expression "$pingcmd $($hostname)") {
foreach ($hostname in $hostnames) {
if (& $pingcmd -count 1 $hostname -ea 0) {
if (! $sawup[$hostname]) {
echo "$([console]::beep(500,300))$hostname is up $(get-date)"
$sawup[$hostname] = $true
$sawdown[$hostname] = $false
}
} else {
if (! $sawdown[$hostname]) {
echo "$([console]::beep(500,300))$hostname is down $(get-date)"
$sawdown[$hostname] = $true
$sawup[$hostname] = $false
}
}
}
sleep $sleeptime
}
pinger microsoft.com,yahoo.com
microsoft.com is down 11/08/2020 17:54:54
yahoo.com is up 11/08/2020 17:54:55
Have a look at PowerShell Jobs. Note that there are better and faster alternatives (like thread jobs, runspaces, etc), but for a beginner, this would be the easiest way. Basically, it starts a new PowerShell process.
A very simple example:
function startPing($ip) {
Start-Job -ScriptBlock {
param ($Address, $Path)
ping.exe $Address -t | foreach {"{0} - {1}" -f (Get-Date), $_ } >> $Path
} -ArgumentList $ip, $dirPath\$ip.txt
}
This simplified example does not take care of stopping the jobs. So depending on what behavior you want, you should look that up.
Also, note there there is also PowerShell's equivalent to ping, Test-Connection

Get the hostname/DNSName of a Hyper-V VM (while VM is OFF) using PowerShell

Can anyone figure out a clever way to grab the Hostname of a VM while it's still Off using PowerShell?
I only know how to grab the VM's Hostname while the VM is still On.
PS: I want the hostname/DNSName of the VM (not to be confused with the VM Name); which aren't the same thing.
You could try
get-vm |select-object -ExpandProperty network* |select-object -ExpandProperty ipaddresses |Resolve-DnsName
to grab the VM's IP address and do a reverse DNS lookup on it.
Bit late to the show here, but I took Greyula-Reyula's quite efficient answer and turned it into a function that gives more feedback on why you may be getting no output from it. I'm relatively new to this level of scripting, so I'm sure there's a more efficient way to do this, but I'm a fan of "verbosity" and try to make my scripts as easy-to-follow for myself as possible in case I want to mess with them again later. :)
Function Get-HVComputerName
{
[CmdletBinding()]
param(
[Alias("ServerName")][Parameter()]
$HVHostName = $env:COMPUTERNAME,
[Alias("ComputerName")][Parameter()]
[string[]]$VMName
)
#VMWare.VimAutomation.Core also has a "Get-VM" cmdlet,
#so unload that module if it's present first
If (Get-Module -Name VMware*) { Remove-Module -Name VMware* -Verbose:$false }
If (!(Get-Module -Name Hyper-V)) { Import-Module -Name Hyper-V -Verbose:$false }
$VMs = Get-VM -ComputerName $HVHostName -Name "*$VMName*"
If ($VMs)
{
$DNSNameArr = #()
If ($VMs.Count -gt 1)
{
Write-Host "`nFound the following VMs on Hyper-V server $HVHostName with name like `"`*$VMName`*`":" -ForegroundColor Green
$VMs.Name | Out-Default
Write-Host ""
}
ForEach ($VM in $VMs)
{
$Name = $VM.Name
If ($VerbosePreference -eq "Continue")
{
Write-Host ""
}
Write-Verbose "VM: $Name found on server $HVHostName"
If ($VM.State -ne "Running")
{
Write-Verbose "VM: $Name is not in a 'running' state. No IP address will be present.`n"
Continue
}
$VMNetAdapters = $VM | Select-Object -ExpandProperty NetworkAdapters
If ($VMNetAdapters)
{
Write-Verbose "VM $Name - Found the following network adapter(s)"
If ($VerbosePreference -eq "Continue")
{
$VMNetAdapters | Out-Default
}
ForEach ($NetAdapter in $VMNetAdapters)
{
$AdapterName = $NetAdapter.Name
$IPAddresses = $NetAdapter | Select-Object -ExpandProperty IPAddresses
If ($IPAddresses)
{
Write-Verbose "VM: $Name - Adapter: `"$AdapterName`" - Found the following IP address(es) on network adapter"
If ($VerbosePreference -eq "Continue")
{
$IPAddresses | Out-Default
}
ForEach ($IP in $IPAddresses)
{
$DNSName = $IP | Resolve-DnsName -Verbose:$false -ErrorAction SilentlyContinue
If ($DNSName)
{
$DNSFound = $true
$VMDNS = [PSCustomObject]#{
VMName = $Name
IP = $IP
DNSName = $DNSName.NameHost
}
$DNSNameArr += $VMDNS
}
Else
{
Write-Warning "VM: $Name - Adapter: `"$AdapterName`" - IP: $IP - No DNS name found"
Continue
}
}
If (!($DNSFound))
{
Write-Warning "VM: $Name - No DNS entries found for any associated IP addresses"
}
Else
{
$DNSFound = $false
}
}
Else
{
Write-Warning "VM: $Name - Adapter: `"$AdapterName`" - No IP address assigned to adapter"
Continue
}
}
}
Else
{
Write-Warning "VM: $Name - No Network adapters found"
Continue
}
}
If ($DNSNameArr)
{
If ($VerbosePreference -eq "Continue")
{
Write-Host ""
}
Return $DNSNameArr
}
Else
{
Write-Warning "No DNS names found for VM(s) with name like $VMName on server $HVHostName"
}
}
Else
{
Write-Warning "No VM found on server $HVHostName with name like $VMName"
}
} #End function Get-HVComputerName

How can I automate Telnet port checking in Powershell?`

I'm currently trying to put together a script that queries AD for a list of computers, pings the computers to determine which ones are still active, and then telnets into a specific port on all the pingable computers. The output I'm looking for is a full list of pingable computers in AD for which I can't telnet to the said port.
I've read these few questions, but they don't quite hit on what I'm trying to do. I just want to see if the telnet connection is successful without entering telnet (or automate the quitting of telnet) and move on to the next machine to test. The AD and pinging portions of my script are set, I'm just stuck here. The things I've tried haven't quite worked as planned.
Here is the code for the first parts of the script, if needed:
Get-ADComputer -Filter * -SearchBase 'DC=hahaha,DC=hehehe' | ForEach {
$computerName = $_.Name
$props = #{
ComputerName = $computerName
Alive = $false
PortOpen = $false
}
If (Test-Connection -ComputerName $computerName -Count 1 -Quiet) {
$props.Alive = $true
}
Adapting this code into your own would be the easiest way. This code sample comes from the PowerShellAdmin wiki. Collect the computer and port you want to check. Then attempt to make a connection to that computer on each port using Net.Sockets.TcpClient.
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 = $null
}
}
Here is a complete powershell script that will:
1. read the host and port details from CSV file
2. perform telnet test
3. write the output with the test status to another CSV file
checklist.csv
remoteHost,port
localhost,80
asdfadsf,83
localhost,135
telnet_test.ps1
$checklist = import-csv checklist.csv
$OutArray = #()
Import-Csv checklist.csv |`
ForEach-Object {
try {
$rh = $_.remoteHost
$p = $_.port
$socket = new-object System.Net.Sockets.TcpClient($rh, $p)
} catch [Exception] {
$myobj = "" | Select "remoteHost", "port", "status"
$myobj.remoteHost = $rh
$myobj.port = $p
$myobj.status = "failed"
Write-Host $myobj
$outarray += $myobj
$myobj = $null
return
}
$myobj = "" | Select "remoteHost", "port", "status"
$myobj.remoteHost = $rh
$myobj.port = $p
$myobj.status = "success"
Write-Host $myobj
$outarray += $myobj
$myobj = $null
return
}
$outarray | export-csv -path "result.csv" -NoTypeInformation
result.csv
"remoteHost","port","status"
"localhost","80","failed"
"asdfadsf","83","failed"
"localhost","135","success"

How to check Network port access and display useful message?

I was trying to check whether the port is opened or not using powershell like follows.
(new-object Net.Sockets.TcpClient).Connect("10.45.23.109", 443)
This method works , but the output is not user-friendly. It means if there are no errors then it has access. Is there any way to check for success and display some message like " Port 443 is operational"?
If you're running Windows 8/Windows Server 2012 or newer, you can use the Test-NetConnection command in PowerShell.
Ex:
Test-NetConnection -Port 53 -ComputerName LON-DC1
I improved Salselvaprabu's answer in several ways:
It is now a function - you can put in your powershell profile and use anytime you need
It can accept host as hostname or as ip address
No more exceptions if host or port unavaible - just text
Call it like this:
Test-Port example.com 999
Test-Port 192.168.0.1 80
function Test-Port($hostname, $port)
{
# This works no matter in which form we get $host - hostname or ip address
try {
$ip = [System.Net.Dns]::GetHostAddresses($hostname) |
select-object IPAddressToString -expandproperty IPAddressToString
if($ip.GetType().Name -eq "Object[]")
{
#If we have several ip's for that address, let's take first one
$ip = $ip[0]
}
} catch {
Write-Host "Possibly $hostname is wrong hostname or IP"
return
}
$t = New-Object Net.Sockets.TcpClient
# We use Try\Catch to remove exception info from console if we can't connect
try
{
$t.Connect($ip,$port)
} catch {}
if($t.Connected)
{
$t.Close()
$msg = "Port $port is operational"
}
else
{
$msg = "Port $port on $ip is closed, "
$msg += "You may need to contact your IT team to open it. "
}
Write-Host $msg
}
Actually Shay levy's answer is almost correct but i got an weird issue as i mentioned in his comment column. So i split the command into two lines and it works fine.
$Ipaddress= Read-Host "Enter the IP address:"
$Port= Read-host "Enter the port number to access:"
$t = New-Object Net.Sockets.TcpClient
$t.Connect($Ipaddress,$Port)
if($t.Connected)
{
"Port $Port is operational"
}
else
{
"Port $Port is closed, You may need to contact your IT team to open it. "
}
You can check if the Connected property is set to $true and display a friendly message:
$t = New-Object Net.Sockets.TcpClient "10.45.23.109", 443
if($t.Connected)
{
"Port 443 is operational"
}
else
{
"..."
}
With the latest versions of PowerShell, there is a new cmdlet, Test-NetConnection.
This cmdlet lets you, in effect, ping a port, like this:
Test-NetConnection -ComputerName <remote server> -Port nnnn
I know this is an old question, but if you hit this page (as I did) looking for this information, this addition may be helpful!
I tried to improve the suggestion from mshutov.
I added the option to use the output as an object.
function Test-Port($hostname, $port)
{
# This works no matter in which form we get $host - hostname or ip address
try {
$ip = [System.Net.Dns]::GetHostAddresses($hostname) |
select-object IPAddressToString -expandproperty IPAddressToString
if($ip.GetType().Name -eq "Object[]")
{
#If we have several ip's for that address, let's take first one
$ip = $ip[0]
}
} catch {
Write-Host "Possibly $hostname is wrong hostname or IP"
return
}
$t = New-Object Net.Sockets.TcpClient
# We use Try\Catch to remove exception info from console if we can't connect
try
{
$t.Connect($ip,$port)
} catch {}
if($t.Connected)
{
$t.Close()
$object = [pscustomobject] #{
Hostname = $hostname
IP = $IP
TCPPort = $port
GetResponse = $True }
Write-Output $object
}
else
{
$object = [pscustomobject] #{
Computername = $IP
TCPPort = $port
GetResponse = $False }
Write-Output $object
}
Write-Host $msg
}
If you are using older versions of Powershell where Test-NetConnection isn't available, here is a one-liner for hostname "my.hostname" and port "123":
$t = New-Object System.Net.Sockets.TcpClient 'my.hostname', 123; if($t.Connected) {"OK"}
Returns OK, or an error message.
Great answer by mshutov & Salselvaprabu. I needed something a little bit more robust, and that checked all IPAddresses that was provided instead of checking only the first one.
I also wanted to replicate some of the parameter names and functionality than the Test-Connection function.
This new function allows you to set a Count for the number of retries, and the Delay between each try. Enjoy!
function Test-Port {
[CmdletBinding()]
Param (
[string] $ComputerName,
[int] $Port,
[int] $Delay = 1,
[int] $Count = 3
)
function Test-TcpClient ($IPAddress, $Port) {
$TcpClient = New-Object Net.Sockets.TcpClient
Try { $TcpClient.Connect($IPAddress, $Port) } Catch {}
If ($TcpClient.Connected) { $TcpClient.Close(); Return $True }
Return $False
}
function Invoke-Test ($ComputerName, $Port) {
Try { [array]$IPAddress = [System.Net.Dns]::GetHostAddresses($ComputerName) | Select-Object -Expand IPAddressToString }
Catch { Return $False }
[array]$Results = $IPAddress | % { Test-TcpClient -IPAddress $_ -Port $Port }
If ($Results -contains $True) { Return $True } Else { Return $False }
}
for ($i = 1; ((Invoke-Test -ComputerName $ComputerName -Port $Port) -ne $True); $i++)
{
if ($i -ge $Count) {
Write-Warning "Timed out while waiting for port $Port to be open on $ComputerName!"
Return $false
}
Write-Warning "Port $Port not open, retrying..."
Sleep $Delay
}
Return $true
}
boiled this down to a one liner sets the variable "$port389Open" to True or false - its fast and easy to replicate for a list of ports
try{$socket = New-Object Net.Sockets.TcpClient($ipAddress,389);if($socket -eq $null){$Port389Open = $false}else{Port389Open = $true;$socket.close()}}catch{Port389Open = $false}
If you want ot go really crazy you can return the an entire array-
Function StdPorts($ip){
$rst = "" | select IP,Port547Open,Port135Open,Port3389Open,Port389Open,Port53Open
$rst.IP = $Ip
try{$socket = New-Object Net.Sockets.TcpClient($ip,389);if($socket -eq $null){$rst.Port389Open = $false}else{$rst.Port389Open = $true;$socket.close();$ipscore++}}catch{$rst.Port389Open = $false}
try{$socket = New-Object Net.Sockets.TcpClient($ip,53);if($socket -eq $null){$rst.Port53Open = $false}else{$rst.Port53Open = $true;$socket.close();$ipscore++}}catch{$rst.Port53Open = $false}
try{$socket = New-Object Net.Sockets.TcpClient($ip,3389);if($socket -eq $null){$rst.Port3389Open = $false}else{$rst.Port3389Open = $true;$socket.close();$ipscore++}}catch{$rst.Port3389Open = $false}
try{$socket = New-Object Net.Sockets.TcpClient($ip,547);if($socket -eq $null){$rst.Port547Open = $false}else{$rst.Port547Open = $true;$socket.close();$ipscore++}}catch{$rst.Port547Open = $false}
try{$socket = New-Object Net.Sockets.TcpClient($ip,135);if($socket -eq $null){$rst.Port135Open = $false}else{$rst.Port135Open = $true;$socket.close();$SkipWMI = $False;$ipscore++}}catch{$rst.Port135Open = $false}
Return $rst
}
When scanning closed port it becomes unresponsive for long time. It seems to be quicker when resolving fqdn to ip like:
[System.Net.Dns]::GetHostAddresses("www.msn.com").IPAddressToString