Как проверить, открыт ли порт на удаленном сервере с пакетным файлом и без стороннего программного обеспечения?

Как этот вопрос закрыт (где я намеревался ответить первым) Я открываю этот.

На некоторых машинах запрещено устанавливать/загружать двоичные файлы, поэтому я хочу знать, как я могу проверить, открыт ли порт на удаленном компьютере, используя только собственные возможности Windows script.

Ответ 1

Успокоившись, Windows не предлагает простые инструменты для проверки того, открыт ли порт на удаленном сервере.

Один из вариантов - telnet, но он не может быть написан по сценарию, поскольку он закрывается, когда его выход перенаправляется или захватывается. Когда-то существовал объект MSWinsock.Winsock.1 COM, установленный на компьютерах Windows, который можно было использовать в script, но не более того. PortQry и PsPing - замечательные инструменты, но вам все равно нужно их загрузить (несмотря на то, что Microsoft предоставила их).

Таким образом, самый простой способ - полагаться на PowerShell.
Вот код для простого .bat script, использующего Powershell, чтобы выполнить задание:

@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%

Некоторые машины имеют платформу .NET без PowerShell, поэтому в этом случае код С# можно вставить в пакетный script с помощью msbuild

<!-- :
    @echo off
    :: checks if a port on a remote server is open
    :: returns errorlevel 1 if it 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>

Что касается машин без .NET framework, я не знаю никаких собственных методов проверки удаленных портов.

Ответ 2

Если вы хотите только проверить TCP-порты, вы можете использовать Test-NetConnection. Если вы предлагаете параметр -Port для определения TCP-порта.