如何在C#中获取开放端口的进程名称?
经过一番搜索后,我将Cheyne Wallace的解决方案改编为静态类,其中一个属性使用NetStat以列表的形式返回进程到端口的映射.
这是班级:
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Text.RegularExpressions; namespace MyNamespace { ////// Static class that returns the list of processes and the ports those processes use. /// public static class ProcessPorts { ////// A list of ProcesesPorts that contain the mapping of processes and the ports that the process uses. /// public static ListProcessPortMap { get { return GetNetStatPorts(); } } /// /// This method distills the output from netstat -a -n -o into a list of ProcessPorts that provide a mapping between /// the process (name and id) and the ports that the process is using. /// ///private static List GetNetStatPorts() { List ProcessPorts = new List (); try { using (Process Proc = new Process()) { ProcessStartInfo StartInfo = new ProcessStartInfo(); StartInfo.FileName = "netstat.exe"; StartInfo.Arguments = "-a -n -o"; StartInfo.WindowStyle = ProcessWindowStyle.Hidden; StartInfo.UseShellExecute = false; StartInfo.RedirectStandardInput = true; StartInfo.RedirectStandardOutput = true; StartInfo.RedirectStandardError = true; Proc.StartInfo = StartInfo; Proc.Start(); StreamReader StandardOutput = Proc.StandardOutput; StreamReader StandardError = Proc.StandardError; string NetStatContent = StandardOutput.ReadToEnd() + StandardError.ReadToEnd(); string NetStatExitStatus = Proc.ExitCode.ToString(); if (NetStatExitStatus != "0") { Console.WriteLine("NetStat command failed. This may require elevated permissions."); } string[] NetStatRows = Regex.Split(NetStatContent, "\r\n"); foreach (string NetStatRow in NetStatRows) { string[] Tokens = Regex.Split(NetStatRow, "\\s+"); if (Tokens.Length > 4 && (Tokens[1].Equals("UDP") || Tokens[1].Equals("TCP"))) { string IpAddress = Regex.Replace(Tokens[2], @"\[(.*?)\]", "1.1.1.1"); try { ProcessPorts.Add(new ProcessPort( Tokens[1] == "UDP" ? GetProcessName(Convert.ToInt16(Tokens[4])) : GetProcessName(Convert.ToInt16(Tokens[5])), Tokens[1] == "UDP" ? Convert.ToInt16(Tokens[4]) : Convert.ToInt16(Tokens[5]), IpAddress.Contains("1.1.1.1") ? String.Format("{0}v6", Tokens[1]) : String.Format("{0}v4", Tokens[1]), Convert.ToInt32(IpAddress.Split(':')[1]) )); } catch { Console.WriteLine("Could not convert the following NetStat row to a Process to Port mapping."); Console.WriteLine(NetStatRow); } } else { if (!NetStatRow.Trim().StartsWith("Proto") && !NetStatRow.Trim().StartsWith("Active") && !String.IsNullOrWhiteSpace(NetStatRow)) { Console.WriteLine("Unrecognized NetStat row to a Process to Port mapping."); Console.WriteLine(NetStatRow); } } } } } catch (Exception ex) { Console.WriteLine(ex.Message); } return ProcessPorts; } /// /// Private method that handles pulling the process name (if one exists) from the process id. /// /// ///private static string GetProcessName(int ProcessId) { string procName = "UNKNOWN"; try { procName = Process.GetProcessById(ProcessId).ProcessName; } catch { } return procName; } } /// /// A mapping for processes to ports and ports to processes that are being used in the system. /// public class ProcessPort { private string _ProcessName = String.Empty; private int _ProcessId = 0; private string _Protocol = String.Empty; private int _PortNumber = 0; ////// Internal constructor to initialize the mapping of process to port. /// /// Name of process to be /// /// /// internal ProcessPort (string ProcessName, int ProcessId, string Protocol, int PortNumber) { _ProcessName = ProcessName; _ProcessId = ProcessId; _Protocol = Protocol; _PortNumber = PortNumber; } public string ProcessPortDescription { get { return String.Format("{0} ({1} port {2} pid {3})", _ProcessName, _Protocol, _PortNumber, _ProcessId); } } public string ProcessName { get { return _ProcessName; } } public int ProcessId { get { return _ProcessId; } } public string Protocol { get { return _Protocol; } } public int PortNumber { get { return _PortNumber; } } } }
从简单的控制台应用程序调用可能如下所示:
using System; namespace MyNamespace { class Program { static void Main(string[] args) { foreach (ProcessPort p in ProcessPorts.ProcessPortMap.FindAll(x => x.ProcessName.ToLower() == "myprocess")) //extension is not needed. { Console.WriteLine(p.ProcessPortDescription); } foreach (ProcessPort p in ProcessPorts.ProcessPortMap.FindAll(x => x.PortNumber == 4444)) { Console.WriteLine(p.ProcessPortDescription); } Console.WriteLine("Press any key to continue..."); Console.ReadLine(); } } }