Test-PSOnePort.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
function Test-PSOnePort
{
  <#
      .SYNOPSIS
      Tests a network port on a remote computer
 
      .DESCRIPTION
      Tests whether a port on a remote computer is responding.
 
      .EXAMPLE
      Test-PSOnePort -ComputerName 127.0.0.1 -Port 4000 -Timeout 1000
      Tests whether port 4000 on the local computer is responding,
      and waits a maximum of 1000 milliseconds
 
      .EXAMPLE
      Test-PSOnePort -ComputerName 127.0.0.1 -Port 4000 -Timeout 1000 -Count 30 -Delay 2000
      Tests 30 times whether port 4000 on the local computer is responding,
      and waits a maximum of 1000 milliseconds inbetween each test
 
      .EXAMPLE
      Test-PSOnePort -ComputerName 127.0.0.1 -Port 4000 -Timeout 1000 -Count 0 -Delay 2000 -ExitOnSuccess
      Continuously tests whether port 4000 on the local computer is responding,
      waits a maximum of 1000 milliseconds inbetween each test,
      and exits as soon as the port is responding
 
      .LINK
      https://powershell.one/tricks/network/porttest
  #>



  param
  (
    [Parameter(Mandatory)]
    [string]
    $ComputerName,
        
    # port number to test
    [Parameter(Mandatory)]
    [int]
    $Port,

    # timeout in milliseconds
    [int]
    $Timeout = 500,

    # number of tries. A value of 0 indicates countinuous testing
    [int]
    [ValidateRange(0,1000)]
    $Count = 1,
        
    # delay (in milliseconds) inbetween continuous tests
    $Delay = 2000,
        
    # when enabled, function returns as soon as port is available
    [Switch]
    $ExitOnSuccess
  )
  $ok = $false
  $c = 0
  $isOnline = $false
  $continuous = $Count -eq 0 -or $Count -gt 1
  try
  {
    do
    {
      $c++
      if ($c -gt $Count -and !$continuous) { 
        # count exceeded
        break
      }
      $start = Get-Date
            
      $tcpobject = [system.Net.Sockets.TcpClient]::new()
      $connect = $tcpobject.BeginConnect($computername,$port,$null,$null) 
      $wait = $connect.AsyncWaitHandle.WaitOne($timeout,$false) 
        
      if(!$wait) { 
        # no response from port
        $tcpobject.Close()
        $tcpobject.Dispose()
                
        Write-Verbose "Port $Port is not responding..."
        if ($continuous) { Write-Host '.' -NoNewline }
      } else { 
        try { 
          # port is reachable
          if ($continuous) { Write-Host '!' -NoNewline }
          [void]$tcpobject.EndConnect($connect)
          $tcpobject.Close()
          $tcpobject.Dispose()
                    
          $isOnline = $true
          if ($ExitOnSuccess)
          {
            $ok = $true
            $delay = 0
          }
        }
        catch { 
          # access to port restricted
          throw "You do not have permission to contact port $Port."
        } 
      } 
      $stop = Get-Date
      $timeUsed = ($stop - $start).TotalMilliseconds
      $currentDelay = $Delay - $timeUsed
      if ($currentDelay -gt 100)
      {
        Start-Sleep -Milliseconds $currentDelay
      }
    
    } until ($ok)
  }
  finally
  {
    # dispose objects to free memory
    if ($tcpobject)
    {
      $tcpobject.Close()
      $tcpobject.Dispose()
    }
  }
  if ($continuous) { Write-Host }
    
  return $isOnline
}