#region << 版 本 注 释 >> /*-------------------------------------------------------------------- * 版权所有 (c) 2026 WenJY 保留所有权利。 * CLR版本:4.0.30319.42000 * 机器名称:Mr.Wen's MacBook Pro * 命名空间:Sln.IntelliBelt.Socket * 唯一标识:E4DF9972-3038-4900-A2C1-507F30B63F54 * * 创建者:WenJY * 电子邮箱: * 创建时间:2026-05-27 11:13:35 * 版本:V1.0.0 * 描述: * *-------------------------------------------------------------------- * 修改人: * 时间: * 修改说明: * * 版本:V1.0.0 *--------------------------------------------------------------------*/ #endregion << 版 本 注 释 >> using System.Diagnostics; using System.Runtime.InteropServices; namespace Sln.IntelliBelt.Socket; /// /// 端口信息查询结果 /// public class PortProcessInfo { public int Port { get; set; } public string ProcessName { get; set; } public int Pid { get; set; } public string LocalAddress { get; set; } public string RemoteAddress { get; set; } public string State { get; set; } public override string ToString() { return $"端口:{Port} | 程序:{ProcessName} | PID:{Pid} | {LocalAddress}->{RemoteAddress} | 状态:{State}"; } } public static class PortHelper { /// /// 根据端口号获取使用该端口的程序信息 /// /// 端口号 /// 程序信息列表 public static List GetProcessByPort(int port) { if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { return GetProcessByPortUnix(port); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return GetProcessByPortWindows(port); } throw new PlatformNotSupportedException("不支持当前操作系统"); } #region Unix (macOS / Linux) private static List GetProcessByPortUnix(int port) { var result = new List(); try { var psi = new ProcessStartInfo { FileName = "lsof", Arguments = $"-i :{port} -n -P", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; using var process = Process.Start(psi); var output = process!.StandardOutput.ReadToEnd(); process.WaitForExit(); var lines = output.Split('\n', StringSplitOptions.RemoveEmptyEntries); // 跳过表头(第一行) foreach (var line in lines.Skip(1)) { var parts = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length < 9) continue; var command = parts[0]; var pidStr = parts[1]; var namePart = parts[8]; // 格式: localhost:port->localhost:port 或 *:port if (!int.TryParse(pidStr, out int pid)) continue; var info = new PortProcessInfo { Port = port, ProcessName = command, Pid = pid }; // 解析地址和状态 ParseUnixConnection(namePart, info); // 如果有状态标识(如 (ESTABLISHED)),取最后一个括号内的内容 var lastPart = parts[^1]; if (lastPart.StartsWith('(') && lastPart.EndsWith(')')) { info.State = lastPart.Trim('(', ')'); } else { info.State = "LISTEN"; } result.Add(info); } } catch (Exception ex) { Console.Error.WriteLine($"执行 lsof 失败: {ex.Message}"); } return result; } private static void ParseUnixConnection(string namePart, PortProcessInfo info) { // 格式类似: localhost:6000->localhost:51183 或 *:51183 var arrowIdx = namePart.IndexOf("->"); if (arrowIdx > 0) { info.LocalAddress = namePart[..arrowIdx]; info.RemoteAddress = namePart[(arrowIdx + 2)..]; } else { info.LocalAddress = namePart; info.RemoteAddress = "-"; } } #endregion #region Windows private static List GetProcessByPortWindows(int port) { var result = new List(); try { // 1. 用 netstat 找到 PID var connections = new List<(string local, string remote, string state, int pid)>(); var psi = new ProcessStartInfo { FileName = "netstat", Arguments = "-ano", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; using var process = Process.Start(psi); var output = process!.StandardOutput.ReadToEnd(); process.WaitForExit(); foreach (var line in output.Split('\n', StringSplitOptions.RemoveEmptyEntries).Skip(4)) { var parts = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length < 5) continue; var localAddr = parts[1]; // 如 0.0.0.0:8080 var remoteAddr = parts[2]; var state = parts.Length == 5 ? "LISTEN" : parts[3]; // 取最后一列作为 PID var lastPart = parts[^1]; if (!int.TryParse(lastPart, out int pid)) continue; // 检查是否匹配目标端口 var localPort = localAddr.Split(':').Last(); var remotePort = remoteAddr.Split(':').Last(); if (localPort == port.ToString() || remotePort == port.ToString()) { connections.Add((localAddr, remoteAddr, state, pid)); } } // 2. 用 tasklist 找程序名 var pidNameMap = new Dictionary(); psi = new ProcessStartInfo { FileName = "tasklist", Arguments = "/FO CSV /NH", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; using var process2 = Process.Start(psi); var tasklistOutput = process2!.StandardOutput.ReadToEnd(); process2.WaitForExit(); foreach (var line in tasklistOutput.Split('\n', StringSplitOptions.RemoveEmptyEntries)) { var trimmed = line.Trim().Trim('"'); var csvParts = trimmed.Split("\",\""); if (csvParts.Length >= 2 && int.TryParse(csvParts[1], out int pid)) { pidNameMap[pid] = csvParts[0]; } } // 3. 组装结果 foreach (var (local, remote, state, pid) in connections) { var processName = pidNameMap.TryGetValue(pid, out var name) ? name : "(未知)"; result.Add(new PortProcessInfo { Port = port, ProcessName = processName, Pid = pid, LocalAddress = local, RemoteAddress = remote, State = state }); } } catch (Exception ex) { Console.Error.WriteLine($"查询失败: {ex.Message}"); } return result; } #endregion /// /// 判断端口是否被本地 Intel 程序(Sln.Intel)占用 /// /// 端口号 /// true 表示端口被本地 Sln.Intel 相关进程占用 public static bool IsIntelLocalPort(int port) { var list = GetProcessByPort(port); return list.Any(info => // 程序名包含 Sln.Intel(忽略大小写) info.ProcessName.Contains("Sln.Intel", StringComparison.OrdinalIgnoreCase) //&& IsLocalAddress(info.RemoteAddress);; // 且连接双方都在本机(localhost 或 127.0.0.1) && IsLocalAddress(info.LocalAddress) && IsLocalAddress(info.RemoteAddress)); } /// /// 判断地址是否为本机地址 /// private static bool IsLocalAddress(string address) { if (string.IsNullOrEmpty(address)) return false; // 支持 localhost、127.0.0.1、*:* 等本机形式 return address.StartsWith("localhost:", StringComparison.OrdinalIgnoreCase) || address.StartsWith("127.0.0.1:", StringComparison.OrdinalIgnoreCase) || address.StartsWith("*:", StringComparison.OrdinalIgnoreCase) || address.StartsWith("[::1]:", StringComparison.OrdinalIgnoreCase) || address.StartsWith("0.0.0.0:", StringComparison.OrdinalIgnoreCase); } #region 便捷方法 /// /// 获取端口对应的第一个程序名称(最常用) /// /// 端口号 /// 程序名,无结果时返回 null public static string? GetProcessNameByPort(int port) { var list = GetProcessByPort(port); return list.FirstOrDefault()?.ProcessName; } /// /// 输出端口占用详情到控制台 /// public static void PrintPortInfo(int port) { var list = GetProcessByPort(port); if (list.Count == 0) { Console.WriteLine($"端口 {port} 没有被任何程序占用"); return; } foreach (var item in list) { Console.WriteLine(item); } } #endregion }