如何在C#应用中执行Test-NetConnection并正确获取返回结果
问题解决方法及替代方案
问题根因
- 未捕获PowerShell实例的非输出流内容:
Invoke()方法默认仅返回成功输出流的内容,命令执行产生的错误、警告、信息类内容会写入其他独立流,不会主动抛出到C#上下文,也不会被默认返回,所以你会拿到空结果但看不到报错。 - Cake.Powershell 1.0.1 版本兼容性问题:该版本默认适配.NET Framework运行时,在.NET 5的CoreCLR环境下执行时存在输出流捕获异常的已知问题。
Test-NetConnection命令本身的输出特性:在非交互会话中执行时,网络不通等场景下的检测结果会写入信息流而非默认输出流,无法被Invoke()直接捕获。
修复方案
首先调整代码补全错误流捕获,同时调整命令输出格式避免流丢失:
PowerShell powerShellInstance = PowerShell.Create(); // 配置进程级执行策略避免权限拦截 powerShellInstance.AddScript("Set-ExecutionPolicy RemoteSigned -Scope Process -Force", true); // 将检测结果转为Json确保输出到默认流 powerShellInstance.AddScript("Test-NetConnection *SomeIPaddress* -port 90 | ConvertTo-Json"); var result = powerShellInstance.Invoke(); // 读取错误流定位问题 if (powerShellInstance.Streams.Error.Count > 0) { foreach (var error in powerShellInstance.Streams.Error) { Console.WriteLine($"PowerShell执行错误:{error}"); } } if (result.Any()) { string rawResult = result.First().BaseObject?.ToString(); // 反序列化rawResult即可拿到完整检测信息 }
如果调整后仍存在捕获异常,将Cake.Powershell NuGet包升级到2.0及以上版本,该版本已完成.NET 5+运行时的适配,修复了流捕获缺陷。
替代实现方案
不需要依赖PowerShell调用,可直接使用.NET原生的TcpClient实现端口检测,性能更高且无环境依赖:
using System.Net.Sockets; public static bool CheckPortConnectivity(string ip, int port, int timeout = 3000) { try { using TcpClient tcpClient = new TcpClient(); var connectAsyncResult = tcpClient.BeginConnect(ip, port, null, null); bool connectSuccess = connectAsyncResult.AsyncWaitHandle.WaitOne(timeout); if (!connectSuccess) { tcpClient.Close(); return false; } tcpClient.EndConnect(connectAsyncResult); tcpClient.Close(); return true; } catch (SocketException) { return false; } }
内容的提问来源于stack exchange,提问作者Tom Boudniatski
相关产品推荐
相关产品推荐

