How to check if port is open on a remote server with batch file and without third party software?

Upsettingly, Windows does not offer simple tools to check whether port is open on a remote server.

One option is telnet but it cannot be scripted as it closes when its output is redirected or captured. Once upon a time there was a MSWinsock.Winsock.1 COM object installed on Windows machines that could be used in a script, but no more. PortQry and PsPing are a wonderful tools but you still have to download them (despite it being provided by Microsoft).

So the easiest way is to rely on PowerShell.
Here is the code for a simple .bat script, internally using Powershell to get the job done :

@echo off

::Must be without quotes. If you intend to use command line arguments use %~1
set "host=google.com"
set /a port=443

for /f %%a in ('powershell "$t = New-Object Net.Sockets.TcpClient;try{$t.Connect("""%host%""", %port%)}catch{};$t.Connected"') do set "open=%%a"
:: or simply
:: powershell "$t = New-Object Net.Sockets.TcpClient;try{$t.Connect("""%host%""", %port%)}catch{};$t.Connected"
echo Open: %open%

Some machines have .NET framework without PowerShell installed so in this case C# code can be embedded into a batch script using msbuild:

<!-- :
    @echo off
    :: checks if a port on a remote server is open
    :: returns errorlevel 1 if it's closed
        setlocal
        for %%h in (/h /help -help -h "") do (
            if /I "%~1" equ "%%~h" (
                goto :printHelp
            )
        )
        
        if "%~2" equ ""  goto :printHelp
        
        set "HOST=%~1"
        set /a PORT=%~2
        
        ::::::  Starting C# code :::::::
        :: searching for msbuild location
        for /r "%SystemRoot%\Microsoft.NET\Framework\" %%# in ("*msbuild.exe") do  set "msb=%%#"

        if not defined  msb (
           echo No .NET framework installed
           endlocal & exit /b 10
        )

        rem ::::::::::  calling msbuid :::::::::
        call %msb% /nologo /noconsolelogger  "%~dpsfnx0"
        rem ::::::::::::::::::::::::::::::::::::
        endlocal & exit /b %errorlevel%
        
        :printHelp
        echo Checks if port is open on a remote server
        echo(
        echo Usage:
        echo    %~nx0 host port
        echo(
        echo If the port is not accessible an errorlevel 1 is set
        endlocal & exit /b 0
      
--> 

<Project ToolsVersion="$(MSBuildToolsVersion)" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="_"><_/></Target>
  <UsingTask TaskName="_" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v$(MSBuildToolsVersion).dll" > 

    <Task>
      <Using Namespace="System" />
      <Using Namespace="System.Net.Sockets" />
 
      <Code Type="Method" Language="cs"><![CDATA[

      public override bool Execute(){
            String host=Environment.GetEnvironmentVariable("HOST").ToLower();
            int port=Int32.Parse(Environment.GetEnvironmentVariable("PORT"));
            
            Console.WriteLine("Checking host {0} and port {1}",host,port);
            using(TcpClient client = new TcpClient()) {
            try {
                client.Connect(host, port);
            } catch(Exception) {
                Console.WriteLine("Closed");
                return false;
            }
            client.Close();
            Console.WriteLine("Open");
            return true;
        }       
      }
        ]]>
      </Code>
    </Task>
  </UsingTask>
</Project>

As for the machines without .NET framework I don't know any native method to check remote ports.

Example usage (if the script is saves as checkport.bat):

C:\>checkport.bat google.com 443
Checking host google.com and port 443
Open

C:\>checkport.bat google.com 666
Checking host google.com and port 666
Closed

Also checkPortJS.bat can be checked - it creates a small executable relying on jscript.net and can be used with the same command line interface. Probably is more portable as it can be used on older systems and the code is easier for reading.


If you only want to check TCP ports you can use Test-NetConnection. If offers a -Port parameter to define the TCP port.


These commands could be used in Powershell:

New-Object System.Net.Sockets.TcpClient("123.12.12.123", "22")
New-Object System.Net.Sockets.UdpClient("123.12.12.123", "22")