Check open ports: Difference between revisions

From NSIS Wiki
Jump to navigationJump to search
(Truncate ntohs return value for Win10.1709 FCU)
(→‎Ports.nsh: Use 16-bit type when calling ntohs if available)
Line 84: Line 84:
       System::Call *$4(i,i.r4)
       System::Call *$4(i,i.r4)
     ${EndIf}
     ${EndIf}
!if ${NSIS_PACKEDVERSION} >= 50343936 ; v3.3+
    System::Call ws2_32::ntohs(hr4)h.r4
!else
     System::Call ws2_32::ntohs(ir4)i.r4
     System::Call ws2_32::ntohs(ir4)i.r4
     IntOp $4 $4 & 0xffff ; Truncate to 16-bits
     IntOp $4 $4 & 0xffff ; Truncate to 16-bits
!endif


     ${If} $4 = $R0
     ${If} $4 = $R0

Revision as of 21:46, 30 November 2017

Below is a function allowing you to test for open UDP and TCP ports on the local computer. Use this to check if the user selected port is free, if Apache can run with the default configuration or if your favorite port hasn't been stolen by another.

This code uses iphlpapi.dll which is only available on Windows 98 and above and NT 4.0 SP4 and above.

Usage

First, save Ports.nsh from the code snippet at the end of this page to Ports.nsh. Next, include it into your script.

!include "Ports.nsh"

Now, to check for open TCP ports, use the following.

${Unless} ${TCPPortOpen} 80
  MessageBox MB_OK "httpd running"
${EndUnless}

To check for open UDP ports, only a slight modification is required.

${If} ${UDPPortOpen} 1337
  MessageBox MB_OK "leet port open :)"
${EndIf}

Ports.nsh

# Usage:
#   Push "Tcp" or "Udp"
#   Push "port_number"
#   Call IsPortOpen
#   Pop $0 ; "open" or "closed" or anything else for error
#
# Or with the LogicLib
#   ${If} ${TCPPortOpen} 80
#   ${EndIf}
#   ${If} ${UDPPortOpen} 137
#   ${EndIf}
#
Function IsPortOpen
 
  Exch $R0 # port to check
  Exch
  Exch $R1
  Push $0
  Push $1
  Push $2
 
  System::Call 'iphlpapi::Get$R1Table(*i.r0, *i .r1, i 1) i .r2'
  ${If} $2 != 122 # ERROR_INSUFFICIENT_BUFFER
    StrCpy $R0 ""
    Pop $2
    Pop $1
    Pop $0
    Exch $R1
    Exch
    Exch $R0
    Return
  ${EndIf}
 
  System::Alloc $1
  Pop $0
 
  System::Call 'iphlpapi::Get$R1Table(ir0, *i r1, i 1) i .r2'
  ${If} $2 != 0 # NO_ERROR
    System::Free $0
    StrCpy $R0 ""
    Pop $2
    Pop $1
    Pop $0
    Exch $R1
    Exch
    Exch $R0
    Return
  ${EndIf}
 
  Push $3
  Push $4
  Push $5
 
  System::Call *$0(i.r2)
  IntOp $2 $2 - 1
  ${For} $3 0 $2
    IntOp $4 $0 + 4  # skip dwNumEntries
    ${If} $R1 == "Tcp"
      IntOp $5 $3 * 20 # sizeof(MIB_TCPROW)
      IntOp $4 $4 + $5 # skip to entry
      System::Call *$4(i.r1,i,i.r4,i,i)
      ${If} $1 <> 2  # $1 = dwState, 2 = MIB_TCP_STATE_LISTEN
        ${Continue}
      ${EndIf}
    ${Else}
      IntOp $5 $3 * 8 # sizeof(MIB_UDPROW)
      IntOp $4 $4 + $5 # skip to entry
      System::Call *$4(i,i.r4)
    ${EndIf}
!if ${NSIS_PACKEDVERSION} >= 50343936 ; v3.3+
    System::Call ws2_32::ntohs(hr4)h.r4
!else
    System::Call ws2_32::ntohs(ir4)i.r4
    IntOp $4 $4 & 0xffff ; Truncate to 16-bits
!endif
 
    ${If} $4 = $R0
      StrCpy $R0 "open"
      ${Break}
    ${EndIf}
  ${Next}
 
  ${If} $R0 != "open"
    StrCpy $R0 "closed"
  ${EndIf}
 
  System::Free $0
 
  Pop $5
  Pop $4
  Pop $3
  Pop $2
  Pop $1
  Pop $0
  Exch $R1
  Exch
  Exch $R0
 
FunctionEnd
 
# LogicLib macros for IsPortOpen
 
!include LogicLib.nsh
 
!macro _PortOpen _a _b _t _f
  !insertmacro _LOGICLIB_TEMP
  Push `${_a}`
  Push `${_b}`
  Call IsPortOpen
  Pop $_LOGICLIB_TEMP
  !insertmacro _== $_LOGICLIB_TEMP "open" `${_t}` `${_f}`
!macroend
!define PortOpen `PortOpen`
 
!macro _TCPPortOpen _a _b _t _f
  !insertmacro _PortOpen Tcp `${_b}` `${_t}` `${_f}`
!macroend
!define TCPPortOpen `"" TCPPortOpen`
 
!macro _UDPPortOpen _a _b _t _f
  !insertmacro _PortOpen Udp `${_b}` `${_t}` `${_f}`
!macroend
!define UDPPortOpen `"" UDPPortOpen`