C#获取Windows进程监听的TCP/UDP端口实例
在Windows操作系统中,开发者常常需要查询某个应用程序所占用的网络资源,特别是它正在监听哪些TCP或UDP端口。本文将探讨如何利用C#语言结合cmd命令行的netstat工具,来自动获取指定进程ID(PID)所绑定的端口列表。这种方法虽然基础且有效,但在实际部署时需要考虑进程执行的性能开销与兼容性。
原理与准备条件
netstat 是Windows系统自带的一个强大的网络统计工具。当运行 netstat -ano 命令时,它会列出所有活动的网络连接以及每个连接对应的进程ID(PID)。这使得我们可以通过对比PID,准确找到目标进程所使用的端口。
要在C#中实现这一过程,我们需要使用 System.Diagnostics.Process 类来外部启动CMD进程,并重定向其标准输入与输出。核心逻辑如下:
- 创建一个后台不显示窗口的CMD进程实例。
- 配置参数以禁止外壳执行,并开启标准输出的重定向。
- 发送
netstat -ano指令并等待返回结果。 - 逐行解析返回文本,筛选出与目标PID匹配的行。
- 从文本中提取并过滤掉重复的端口号码。
第1步:初始化CMD进程环境
首先需要构造一个 Process 对象,并正确设置其启动参数。为了避免弹出的黑色控制台窗口干扰主程序界面,必须将 CreateNoWindow 设为 true,同时将 UseShellExecute 设为 false 以便重定向流。
// 定义要查询的进程 ID
int pid = ProcInfo.ProcessID;
// 存放该进程使用的所有唯一端口号
List<int> ports = new List<int>();
// 创建新的进程对象用于运行 cmd.exe
Process pro = new Process();
pro.StartInfo.FileName = "cmd.exe";
pro.StartInfo.UseShellExecute = false;
pro.StartInfo.RedirectStandardInput = true;
pro.StartInfo.RedirectStandardOutput = true;
pro.StartInfo.RedirectStandardError = true;
pro.StartInfo.CreateNoWindow = true;
第2步:执行指令并接收数据
启动进程后,向标准输入中写入 netstat -ano 指令。随后使用正则表达式简化待解析的行结构——通常将多个连续的空白字符替换为单个逗号,这样便于后续切分字符串字段。
pro.Start();
pro.StandardInput.WriteLine("netstat -ano");
pro.StandardInput.WriteLine("exit"); // 防止控制台无限期挂起
// 编译正则:将连续空格替换为逗号,方便 Split 操作
Regex reg = new Regex("\\s+", RegexOptions.Compiled);
string line = null;
while ((line = pro.StandardOutput.ReadLine()) != null)
{
line = line.Trim();
if (string.IsNullOrEmpty(line)) continue;
// 进行下一阶段的判断与解析...
}
第3步:解析TCP连接信息
netstat -ano 的输出通常按协议分组。在处理 TCP 连接时,格式一般为:TCP 本地地址 : 端口 状态 PID。由于不同的网络适配器(IPv4/IPv6)可能会产生不同列数偏移的情况,此处采用通用的分割方式。假设解析出的数组 arr 中,最后一个元素(索引 4)是 PID,中间包含了地址与端口信息。
if (line.StartsWith("TCP", StringComparison.OrdinalIgnoreCase))
{
string cleanedLine = reg.Replace(line, ",");
string[] arr = cleanedLine.Split(',');
// 注意:实际环境中,如果存在 IPv6 映射,列位置可能有所变化。
// 一般规则下,倒数第二列为 PID,倒数第三列为地址。
if (arr.Length >= 5 && arr[4] == pid.ToString())
{
string soc = arr[1]; // 例如:0.0.0.0:8080 或 [::]:8080
int pos = soc.LastIndexOf(':');
if (pos > 0)
{
int pot = int.Parse(soc.Substring(pos + 1));
ports.Add(pot);
}
}
}
第4步:解析UDP绑定信息
对于 UDP,因为没有“状态”这一列,其输出格式略有不同:UDP 本地地址 : 端口 PID。在这里,最后的一列即为 PID。处理方式类似,通过查找冒号后的数字获取端口。
else if (line.StartsWith("UDP", StringComparison.OrdinalIgnoreCase))
{
string cleanedLine = reg.Replace(line, ",");
string[] arr = cleanedLine.Split(',');
// 对于 UDP 而言,末尾通常直接就是 PID
if (arr.Length >= 3 && arr[3].Trim() == pid.ToString())
{
string soc = arr[1];
int pos = soc.LastIndexOf(':');
if (pos > 0)
{
int pot = int.Parse(soc.Substring(pos + 1));
ports.Add(pot);
}
}
}
完成状态验证
循环结束后,调用 pro.Close() 释放 CMD 占用的系统资源。此时,ports 集合中便存有目标进程正在监听的所有 TCP 和 UDP 端口号。如果需要进一步去重,可遍历该集合或使用 LINQ 的 Distinct() 方法。
简要总结
上述方法是一种简单直接的方式,能够无需引用额外的第三方库即可在C#程序中获取Windows进程的网络端口分配情况。需要注意的是,该方法依赖于CMD工具的默认输出格式,在某些特殊的多网卡或者复杂的IPv6网络环境下可能需要针对列位置做微调修正。
以上就是C#获取Windows进程监听的TCP/UDP端口的详细内容,更多关于C#开发技巧的资料请关注本站其它相关文章!本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













