Ответ 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, я не знаю никаких собственных методов проверки удаленных портов.