问题
How do I get process name of an open port in C#?
回答1:
After some searching, I've adapted Cheyne Wallace's solution into a static class with one property that returns a mapping of Processes to Ports in the form of a list using NetStat.
Here's the class:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
namespace MyNamespace
{
/// <summary>
/// Static class that returns the list of processes and the ports those processes use.
/// </summary>
public static class ProcessPorts
{
/// <summary>
/// A list of ProcesesPorts that contain the mapping of processes and the ports that the process uses.
/// </summary>
public static List<ProcessPort> ProcessPortMap
{
get
{
return GetNetStatPorts();
}
}
/// <summary>
/// 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.
/// </summary>
/// <returns></returns>
private static List<ProcessPort> GetNetStatPorts()
{
List<ProcessPort> ProcessPorts = new List<ProcessPort>();
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;
}
/// <summary>
/// Private method that handles pulling the process name (if one exists) from the process id.
/// </summary>
/// <param name="ProcessId"></param>
/// <returns></returns>
private static string GetProcessName(int ProcessId)
{
string procName = "UNKNOWN";
try
{
procName = Process.GetProcessById(ProcessId).ProcessName;
}
catch { }
return procName;
}
}
/// <summary>
/// A mapping for processes to ports and ports to processes that are being used in the system.
/// </summary>
public class ProcessPort
{
private string _ProcessName = String.Empty;
private int _ProcessId = 0;
private string _Protocol = String.Empty;
private int _PortNumber = 0;
/// <summary>
/// Internal constructor to initialize the mapping of process to port.
/// </summary>
/// <param name="ProcessName">Name of process to be </param>
/// <param name="ProcessId"></param>
/// <param name="Protocol"></param>
/// <param name="PortNumber"></param>
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; }
}
}
}
Calling from a simple console application may look like:
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();
}
}
}
回答2:
http://www.codeproject.com/KB/IP/iphlpapi.aspx might also help
回答3:
You can execute netstat -anb
and process output.
回答4:
I had this same issue not long ago. There isnt an easy way to do this using .net alone. You retrieve the port numbers and the process id's but not the relation between the two.
This bit of code uses NetStat to work it out.
Get Active Ports and Associated Process Names In C#
http://www.cheynewallace.com/get-active-ports-and-associated-process-names-in-c/
来源:https://stackoverflow.com/questions/1675077/how-do-i-get-process-name-of-an-open-port-in-c