Functions/Test-Port.ps1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
function Test-Port { <# .SYNOPSIS Tests a Port or a range of ports on a specific ComputerName(s). .DESCRIPTION Tests a Port or a range of ports on a specific ComputerName(s). Creates a custom object with the properties: ComputerName, Protocol, Port, Open, Notes. .PARAMETER ComputerName A single ComputerName or array of ComputerName to test the port connection on. Aliased to 'CN', 'Server' .PARAMETER Port Port number to test ([int16] 0 - 65535), an array can also be passed .PARAMETER TCP Use TCP as the transport protocol .PARAMETER UDP Use UDP as the transport protocol .PARAMETER TimeOut Sets a timeout for TCP or UDP port query. (In milliseconds, Default is 1000) .EXAMPLE Test-Port -ComputerName 'server' -port 80 Checks port 80 on server 'server' to see if it is listening .EXAMPLE 'server' | Test-Port -Port 80 Checks port 80 on server 'server' to see if it is listening .EXAMPLE Test-Port -ComputerName @("server1","server2") -Port 80 Checks port 80 on server1 and server2 to see if it is listening .EXAMPLE @("server1","server2") | Test-Port -Port 80 Checks port 80 on server1 and server2 to see if it is listening .EXAMPLE (Get-Content hosts.txt) | Test-Port -Port 80 Checks port 80 on servers in host file to see if it is listening .EXAMPLE Test-Port -ComputerName (Get-Content hosts.txt) -Port 80 Checks port 80 on servers in host file to see if it is listening .EXAMPLE Test-Port -ComputerName (Get-Content hosts.txt) -Port @(1..59) Checks a range of ports from 1-59 on all servers in the hosts.txt file .OUTPUTS [psobject] An array of objects containing the fields: ComputerName A string containing the computer name or ip address that was passed to the function Protocol A string being either 'TCP' or 'UDP' Port An integer in the range 1 - 65535 Open A boolean Notes Any notes when attempting to make a connection .LINK about_Properties .NOTES # inspired by https://gallery.technet.microsoft.com/scriptcenter/97119ed6-6fb2-446d-98d8-32d823867131 #> #region Parameter [CmdletBinding(ConfirmImpact = 'Low')] [OutputType('psobject')] Param( [Parameter(Mandatory, HelpMessage = 'Enter a ComputerName or IP address', Position = 0, ValueFromPipeline)] [Alias('CN', 'Server')] [string[]] $ComputerName, [Parameter(Position = 1, Mandatory, HelpMessage = 'Enter an integer port number (1-65535)')] [uint16[]] $Port, [int] $Timeout = 1000, [switch] $TCP, [switch] $UDP ) #endregion Parameter begin { Write-Verbose -Message "Starting [$($MyInvocation.Mycommand)]" if (!$tcp -AND !$udp) { $tcp = $True } #Typically you never do this, but in this case I felt it was for the benefit of the function #as any errors will be noted in the output of the report $oldEA = $ErrorActionPreference $ErrorActionPreference = 'SilentlyContinue' Write-Verbose -Message "Saving current value of `$ErrorActionPreference [$($oldEa)] and setting it to 'Stop'" } process { foreach ($c in $ComputerName) { foreach ($p in $port) { if ($tcp) { #Create temporary holder #$temp = '' | Select-Object -Property ComputerName, Protocol, Port, Open, Notes $temp = New-Object -TypeName psobject -Property @{ Computername = ''; Protocol = ''; Port = 0; Open = $false; Notes = '' } #Create object for connecting to port on computer $tcpobject = New-Object -TypeName system.Net.Sockets.TcpClient #Connect to remote machine's port $connect = $tcpobject.BeginConnect($c, $p, $null, $null) #Configure a timeout before quitting $wait = $connect.AsyncWaitHandle.WaitOne($Timeout, $false) #if timeout if (!$wait) { #Close connection $tcpobject.Close() Write-Verbose -Message 'Connection Timeout' #Build report $temp.ComputerName = $c $temp.Port = $p $temp.Protocol = 'TCP' $temp.Open = $false $temp.Notes = 'Connection to Port Timed Out' } else { $error.Clear() $null = $tcpobject.EndConnect($connect) #if error if ($error[0]) { #Begin making error more readable in report [string] $string = ($error[0].exception).message $message = (($string.split(':')[1]).replace('"', '')).TrimStart() $failed = $true } #Close connection $tcpobject.Close() #if unable to query port to due failure if ($failed) { #Build report $temp.ComputerName = $c $temp.Port = $p $temp.Protocol = 'TCP' $temp.Open = $false $temp.Notes = "$message" } else { #Build report $temp.ComputerName = $c $temp.Port = $p $temp.Protocol = 'TCP' $temp.Open = $true $temp.Notes = "Successful link to $c $($temp.Protocol) port $p" } } #Reset failed value $failed = $Null #Merge temp array with report Write-Output -InputObject $temp } if ($udp) { #$temp = '' | Select-Object -Property ComputerName, Protocol, Port, Open, Notes $temp = New-Object -TypeName psobject -Property @{ Computername = ''; Protocol = ''; Port = 0; Open = $false; Notes = '' } Write-Verbose -Message 'Making UDP connection to remote server' $Socket = New-Object -TypeName Net.Sockets.Socket -ArgumentList ( 'InterNetwork', 'Dgram', 'Udp' ) $Socket.SendTimeOut = $Timeout # ms $Socket.ReceiveTimeOut = $Timeout # ms try { $Socket.Connect( $C, $p ) $Buffer = New-Object -TypeName byte[] -ArgumentList 48 $Buffer[0] = 27 Write-Verbose -Message 'Sending message to remote host' $null = $Socket.Send( $Buffer ) $null = $Socket.Receive( $Buffer ) $temp.ComputerName = $c $temp.Port = $p $temp.Protocol = 'UDP' $temp.Open = $true $temp.Notes = '' } catch { Write-Verbose -Message 'Communication failed' Write-Error -Message $error[0] $temp.ComputerName = $c $temp.Port = $p $temp.Protocol = 'UDP' $temp.Open = $false $temp.Notes = $error[0].exception } $socket.dispose() Remove-Variable -Name socket #Merge temp array with report Write-Output -InputObject $temp } } } } end { #Generate Report #Write-Output -InputObject $report Write-Verbose -Message "Resetting value of `$ErrorActionPreference back to [$($oldEa)]" $ErrorActionPreference = $oldEA Write-Verbose -Message "Ending [$($MyInvocation.Mycommand)]" } } |