在 C# 中从 Process.Start 启动 cmd.exe 时,Telnet 不是可识别的命令

Telnet is not recognized command when cmd.exe is started from Process.Start in C#

我已经打开了控制面板上的 telnet 选项 - program/features。 虽然 telnet 手动工作正常,但是当我从我的 C# 库中 运行 下面时,我收到此错误:

"'telnet' is not recognized as an internal or external command, operable program or batch file."

这是我用来启动 Telnet 的代码:

Process.Start("cmd", "/k telnet")

这与从命令提示符手动 运行 有什么区别?我该如何克服这个区别?

Telnet 是一个程序,总是 安装在系统文件夹中。这也意味着,它总是在路上。您不需要开始cmd.exe才能开始telnet.exe。只需使用

Process.Start("telnet.exe");

使用 arguments 参数将参数传递给 telnet 本身,例如主机、日志文件等:

Process.Start("telnet.exe","localhost 80 -f mylog.txt");

还有其他可能更好的选择。

使用 Telnet 库

您可以使用 Telnet 库并直接连接到服务器,例如使用 Telnet NuGet package :

using (Client client = new Client("localhost",80, new System.Threading.CancellationToken()))
{
    await client.WriteLine("abcd");
    string response = await client.ReadAsync();
    Console.WriteLine(response);
}

使用 PowerShell

Telnet 通常用于测试与 Web 服务器的连接,而不是实际发送命令。在这种情况下,您可以使用 PowerShell 的 Test-NetConnection 接收有关连接的诊断信息:

using System.Management.Automation;

var ps = PowerShell.Create()
                    .AddCommand("test-netconnection")
                    .AddArgument("localhost")
                    .AddParameter("CommonTCPPort", "HTTP");
var results = cmd.Invoke();
foreach (dynamic result in results)
{
    Console.WriteLine($"{result.TcpTestSucceeded} {result.SourceAddress}");
}

确保添加正确的 Powershell NuGet 包 Microsoft.PowerShell.5.ReferenceAssemblies,而不是不受支持和废弃的 System.Management.Automation

PowerShell 的优势在于您只需添加更多 AddComandAddScript 调用即可将命令和脚本链接在一起。每个命令都将接收前一个命令的输出。您可以使用 Import-CSV 从文件中读取服务器和端口列表,并将输出通过管道传输到 Test-NetConnection

通过控制面板-程序和功能-打开或关闭Windows功能安装Telnet客户端安装telnet.exe 进入目录 %SystemRoot%\System32.

目录 %SystemRoot%\System32 用于 64 位 Windows 上的 64 位应用程序。因此安装的可执行文件 telnet.exe 也是 64 位版本。此目录还包含 cmd.exe.

的 64 位版本

系统环境变量PATH包含%SystemRoot%\System32,负责查找%SystemRoot%\System32\cmd.exe%SystemRoot%\System32\telnet.exe执行时不带文件扩展名不带路径.

但另外还有目录 %SystemRoot%\SysWOW64 用于 32 位应用程序,其中包含 32 位版本的可执行文件。

Microsoft 在文档页面 WOW64 Implementation Details and File System Redirector 中解释了 32 位应用程序对 %SystemRoot%\System32 的文件系统访问如何自动重定向到 %SystemRoot%\SysWOW64

在安装 Telnet Client.

%SystemRoot%\SysWOW64 中没有安装 32 位版本的 telnet.exe

那么发生了什么:

Process.Start("cmd", "/k telnet")

当 C# 库编译为 64 位应用程序使用的 64 位库时,64 位 Windows 查找并启动 %SystemRoot%\System32\cmd.exe,后者查找并启动 %SystemRoot%\System32\telnet.exe .

但是当 C# 库被编译为 32 位应用程序使用的 32 位库时,64 位 Windows 通过文件系统重定向器 %SystemRoot%\SysWOW64\cmd.exe 查找并启动,它找不到 telnet.* 文件扩展名在当前目录或环境变量 PATH 的环境变量 PATHEXT 中列出,因为没有文件 telnet.exe 在目录 %SystemRoot%\SysWOW64.


最好的解决方案肯定是在 C# 库中使用静态(或动态)telnet 库来独立于 telnet.exe,正如 Panagiotis Kanavos. In my point of view it is a shame for every C# programmer using external executables via a process call for which C# code can be quite easily also written by the programmer. Using any world wide web search engine with the search term C# telnet returns lots of pages with solutions, for example C# Telnet Library 在 Stack Overflow 上所建议的那样。

当然也可以使用GetEnvironmentVariable method to get path to Windows directory, or even better using GetWindowsDirectory or GetSystemWindowsDirectory方法获取环境变量SystemRoot的第一个值。

然后将此字符串值与 "\System32\telnet.exe" 连接成一个新字符串,并使用 File.Exists 方法检查具有该完整路径的文件是否存在。如果该文件存在于安装了 32 位版本 telnet.exe 的 32 位 Windows 如果 C# 应用程序也是 32 位应用程序,或者存在于安装了 64 位 Windows 的 64 位 Windows =11=] 如果 C# 应用程序是 64 位应用程序,则安装此文件名以及完整路径和文件扩展名可以在进程调用中使用。

否则将 Windows 目录路径与 "\Sysnative\telnet.exe" 连接起来,并检查是否存在具有该完整路径的文件。如果在 64 位 Windows 上安装了 64 位版本的 telnet.exe 如果 C# 应用程序是 32 位应用程序,则可以从 32 位 运行使用此路径应用 64 位 telnet 客户端可执行文件。

但如果同样失败,则根本不会安装 telnet.exe,这就是为什么通常不建议在 C# 代码应用程序中使用 telnet.exe 的原因。

老实说,我不明白为什么要在 C# 库中包含代码,它只是启动命令进程执行 telnet.exe 而没有选项,因此需要用户输入并保持命令进程 运行 telnet 客户端会话终止后 ning。 C# 库函数可以在 Windows 桌面或 Windows 用户的开始菜单中替换为 telnet.exe 的快捷方式。