C#获取Windows进程监听的TCP/UDP端口实例

咖啡半糖
咖啡半糖
发布时间:2026-10-14| 6人浏览过
原创

在Windows操作系统中,开发者常常需要查询某个应用程序所占用的网络资源,特别是它正在监听哪些TCP或UDP端口。本文将探讨如何利用C#语言结合cmd命令行的netstat工具,来自动获取指定进程ID(PID)所绑定的端口列表。这种方法虽然基础且有效,但在实际部署时需要考虑进程执行的性能开销与兼容性。

原理与准备条件

netstat 是Windows系统自带的一个强大的网络统计工具。当运行 netstat -ano 命令时,它会列出所有活动的网络连接以及每个连接对应的进程ID(PID)。这使得我们可以通过对比PID,准确找到目标进程所使用的端口。

要在C#中实现这一过程,我们需要使用 System.Diagnostics.Process 类来外部启动CMD进程,并重定向其标准输入与输出。核心逻辑如下:

  1. 创建一个后台不显示窗口的CMD进程实例。
  2. 配置参数以禁止外壳执行,并开启标准输出的重定向。
  3. 发送 netstat -ano 指令并等待返回结果。
  4. 逐行解析返回文本,筛选出与目标PID匹配的行。
  5. 从文本中提取并过滤掉重复的端口号码。

第1步:初始化CMD进程环境

首先需要构造一个 Process 对象,并正确设置其启动参数。为了避免弹出的黑色控制台窗口干扰主程序界面,必须将 CreateNoWindow 设为 true,同时将 UseShellExecute 设为 false 以便重定向流。

// 定义要查询的进程 ID
int pid = ProcInfo.ProcessID;
// 存放该进程使用的所有唯一端口号
List<int> ports = new List<int&gt();

// 创建新的进程对象用于运行 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#开发技巧的资料请关注本站其它相关文章!
相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。