如何检查端口是否在具有批处理文件且没有第三方软件的远程服务器上打开?

npo*_*aka 8 c# windows powershell cmd batch-file

由于这个问题 已经结束(我打算先回答)我正在打开这个问题.

在某些机器上禁止安装/下载二进制文件,因此我想知道如何使用本机Windows脚本功能检查远程计算机上的端口是否打开.

npo*_*aka 17

令人沮丧的是,Windows不提供简单的工具来检查端口是否在远程服务器上打开.

一个选项是telnet,但它不能编写脚本,因为它在重定向或捕获输出时关闭.曾几何时,Windows机器上安装了一个可以在脚本中使用的MSWinsock.Winsock.1 COM对象,但不多了.PortQryPsPing是一个很棒的工具,但你仍然需要下载它们(尽管它是由微软提供的).

所以最简单的方法就是依赖PowerShell.
下面是一个简单的.bat脚本的代码,在内部使用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%
Run Code Online (Sandbox Code Playgroud)

有些机器没有安装PowerShell的.NET框架,因此在这种情况下,可以使用msbuild将C#代码嵌入到批处理脚本中:

<!-- :
    @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>
Run Code Online (Sandbox Code Playgroud)

对于没有.NET框架的机器,我不知道检查远程端口的任何本机方法.


Moe*_*ald 6

如果您只想检查TCP端口,可以使用Test-NetConnection.如果提供了一个-Port参数来定义TCP端口.

  • 是啊.我知道 - 但这是一个4 cmd的powershell让我想尽可能向后兼容.+ 1无论如何. (2认同)

Erd*_*AYA 5

这些命令可以在 Powershell 中使用:

New-Object System.Net.Sockets.TcpClient("123.12.12.123", "22")
New-Object System.Net.Sockets.UdpClient("123.12.12.123", "22")
Run Code Online (Sandbox Code Playgroud)