You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET中如何获取进程正在监听的端口?

纯.NET代码获取进程监听端口的方案

当然可以用纯.NET类库实现,不需要调用PowerShell命令解析输出,以下是两种可行的方案:

方案一:使用System.Net.NetworkInformation命名空间

.NET自带的IPGlobalProperties类可以获取系统的TCP连接信息,结合Process类就能关联到对应的进程监听端口:

using System;
using System.Diagnostics;
using System.Net.NetworkInformation;

class Program
{
    static void Main()
    {
        // 获取系统所有TCP连接信息
        IPGlobalProperties properties = IPGlobalProperties.GetIPGlobalProperties();
        TcpConnectionInformation[] tcpConnections = properties.GetActiveTcpConnections();

        foreach (var conn in tcpConnections)
        {
            // 筛选处于监听状态的连接
            if (conn.State == TcpState.Listen)
            {
                try
                {
                    // 通过进程ID获取进程实例
                    Process process = Process.GetProcessById(conn.OwningProcess);
                    Console.WriteLine($"进程名: {process.ProcessName}, 监听端口: {conn.LocalEndPoint.Port}, PID: {conn.OwningProcess}");
                }
                catch (ArgumentException)
                {
                    // 进程可能已退出,直接输出端口信息
                    Console.WriteLine($"PID: {conn.OwningProcess} 对应的进程已不存在,监听端口: {conn.LocalEndPoint.Port}");
                }
            }
        }
    }
}

注意:该方法需要以管理员权限运行程序,否则可能无法获取部分进程的端口关联信息。

方案二:通过P/Invoke调用Windows API

如果需要更底层的控制或兼容更多场景(比如UDP监听),可以直接调用Windows原生的GetExtendedTcpTable API实现:

using System;
using System.Diagnostics;
using System.Net;
using System.Runtime.InteropServices;

class TcpPortHelper
{
    [StructLayout(LayoutKind.Sequential)]
    private struct MIB_TCPTABLE_OWNER_PID
    {
        public uint dwNumEntries;
        [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)]
        public MIB_TCPROW_OWNER_PID[] table;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct MIB_TCPROW_OWNER_PID
    {
        public uint dwState;
        public uint dwLocalAddr;
        public uint dwLocalPort;
        public uint dwRemoteAddr;
        public uint dwRemotePort;
        public uint dwOwningPid;
    }

    [DllImport("iphlpapi.dll", SetLastError = true)]
    private static extern uint GetExtendedTcpTable(IntPtr pTcpTable, ref uint pdwSize, bool bOrder, uint ulAf, uint TableClass, uint Reserved);

    public static void GetAllTcpListenerProcesses()
    {
        uint bufferSize = 0;
        // 先调用一次获取所需内存大小
        GetExtendedTcpTable(IntPtr.Zero, ref bufferSize, true, 2, 5, 0);

        IntPtr tcpTablePtr = Marshal.AllocHGlobal((int)bufferSize);
        try
        {
            uint result = GetExtendedTcpTable(tcpTablePtr, ref bufferSize, true, 2, 5, 0);
            if (result != 0) return;

            MIB_TCPTABLE_OWNER_PID tcpTable = Marshal.PtrToStructure<MIB_TCPTABLE_OWNER_PID>(tcpTablePtr);
            MIB_TCPROW_OWNER_PID[] rows = new MIB_TCPROW_OWNER_PID[tcpTable.dwNumEntries];
            IntPtr rowPtr = (IntPtr)((long)tcpTablePtr + Marshal.SizeOf(tcpTable.dwNumEntries));

            for (int i = 0; i < tcpTable.dwNumEntries; i++)
            {
                rows[i] = Marshal.PtrToStructure<MIB_TCPROW_OWNER_PID>(rowPtr);
                rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(typeof(MIB_TCPROW_OWNER_PID)));

                // 筛选监听状态(MIB_TCP_STATE_LISTEN对应值为2)
                if (rows[i].dwState == 2)
                {
                    // 转换端口字节序
                    ushort localPort = (ushort)((rows[i].dwLocalPort >> 8) | (rows[i].dwLocalPort << 8));
                    IPAddress localAddr = new IPAddress(rows[i].dwLocalAddr);

                    try
                    {
                        Process process = Process.GetProcessById((int)rows[i].dwOwningPid);
                        Console.WriteLine($"进程名: {process.ProcessName}, PID: {rows[i].dwOwningPid}, 监听地址: {localAddr}:{localPort}");
                    }
                    catch (ArgumentException)
                    {
                        Console.WriteLine($"PID: {rows[i].dwOwningPid} 已退出,监听地址: {localAddr}:{localPort}");
                    }
                }
            }
        }
        finally
        {
            Marshal.FreeHGlobal(tcpTablePtr);
        }
    }
}

// 调用示例
class Program
{
    static void Main()
    {
        TcpPortHelper.GetAllTcpListenerProcesses();
    }
}

说明:

  • 代码默认针对IPv4,若需支持IPv6,需将ulAf参数改为23,并替换为对应的IPv6结构体
  • 同样需要管理员权限才能完整获取所有进程的端口关联信息

内容的提问来源于stack exchange,提问作者rams

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 23:40:21