360安全卫士里面有个组件叫流量防火墙,感觉挺好用,但是不想安装360全家桶,于是自己捣鼓着用C#写一个比较简化的版本。
查看电脑上开启的TCP或UDP端口,可以用netstat命令,netstat用法如下:
显示协议统计和当前 TCP/IP 网络连接。 NETSTAT [-a] [-b] [-e] [-f] [-n] [-o] [-p proto] [-r] [-s] [-t] [interval] -a 显示所有连接和侦听端口。 -b 显示在创建每个连接或侦听端口时涉及的可执行程序。 在某些情况下,已知可执行程序承载多个独立的 组件,这些情况下,显示创建连接或侦听端口时涉 及的组件序列。此情况下,可执行程序的名称 位于底部[]中,它调用的组件位于顶部,直至达 到 TCP/IP。注意,此选项可能很耗时,并且在您没有 足够权限时可能失败。 -e 显示以太网统计。此选项可以与 -s 选项结合使用。 -f 显示外部地址的完全限定域名(FQDN)。 -n 以数字形式显示地址和端口号。 -o 显示拥有的与每个连接关联的进程 ID。 -p proto 显示 proto 指定的协议的连接;proto 可以是下列任 何一个: TCP、UDP、TCPv6 或 UDPv6。如果与 -s 选 项一起用来显示每个协议的统计,proto 可以是下列任 何一个: IP、IPv6、ICMP、ICMPv6、TCP、TCPv6、UDP 或 UDPv6。 -r 显示路由表。 -s 显示每个协议的统计。默认情况下,显示 IP、IPv6、ICMP、ICMPv6、TCP、TCPv6、UDP 和 UDPv6 的统计;-p 选项可用于指定默认的子网。 -t 显示当前连接卸载状态。 interval 重新显示选定的统计,各个显示间暂停的间隔秒数。 按 CTRL+C 停止重新显示统计。如果省略,则 netstat 将打印当前的配置信息一次。
之前也有接触过netstat命令,因为开发的软件写死了端口,有时候开启失败,这时候会用netstat -ano|find "xxx"查看端口是否已经存在,得到对应的PID,再用这个PID去tasklist去查询程序名称。今日认真查看了netstat的用法才知道它就提供了查看对应程序名的参数,即 -b 参数。
不过需要注意的地方是加入-b参数后,得到的程序名和PID并不在同一行,而是在PID的下一行。而且有些系统级别的程序并不能获取到程序名。
以下是代码参考,一开始并不知道-b参数的存在,获取程序名用的是根据PID得到程序名的方法。netstat内部应该也是根据这个拿到程序名的。using System;
using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Diagnostics; using System.Management; using System.Runtime.InteropServices; using System.Text.RegularExpressions; namespace PortManage { public partial class Form1 : Form { const Int32 PROCESS_ALL_ACCESS = 0x1F0FFF; const Int32 PROCESS_QUERY_INFORMATION = 0x00000400; const Int32 PROCESS_VM_READ = 0x0010; const Int32 PROCESS_VM_WRITE = 0x0020; [DllImport("Kernel32.dll", EntryPoint = "QueryFullProcessImageNameW", CharSet = CharSet.Auto)] extern static Int32 QueryFullProcessImageNameW(Int32 hProcess, UInt32 flags, char[] nameList, ref UInt32 nameLen); [DllImport("kernel32.dll")] public static extern Int32 OpenProcess(Int32 DesiredAccess, bool bInheritHandle, Int32 ProcessId); [DllImport("kernel32.dll", SetLastError = true)] static extern bool CloseHandle(Int32 hObject); [DllImport("kernel32.dll")] public static extern Int32 GetLastError(); public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { ShowInfo(); } private void ShowInfo() { List infoList = new List(); List nameList = new List(); System.Diagnostics.ProcessStartInfo procInfo = new System.Diagnostics.ProcessStartInfo(); System.Diagnostics.Process pro = new System.Diagnostics.Process(); pro.StartInfo.FileName = "cmd"; pro.StartInfo.UseShellExecute = false; pro.StartInfo.RedirectStandardInput = true; pro.StartInfo.RedirectStandardOutput = true; pro.StartInfo.RedirectStandardError = true; pro.StartInfo.CreateNoWindow = true; pro.Start(); pro.StandardInput.WriteLine("netstat -anob"); pro.StandardInput.WriteLine("exit"); Regex reg = new Regex("\\s+", RegexOptions.Compiled); string line = null; infoList.Clear(); nameList.Clear(); while ((line = pro.StandardOutput.ReadLine()) != null) { line = line.Trim(); if (line.StartsWith("TCP", StringComparison.OrdinalIgnoreCase)) { line = reg.Replace(line, ","); infoList.Add(line); } if (line.StartsWith("UDP", StringComparison.OrdinalIgnoreCase)) { line = reg.Replace(line, ","); infoList.Add(line); } if (line.StartsWith("[")) { line = line.Replace("[", ""); line = line.Replace("]", ""); nameList.Add(line); } else if (line.StartsWith("无法")) { nameList.Add(""); } } pro.Close(); for (int i = 0; i < infoList.Count; i++) { if (infoList[i].ToString().Split(‘,‘)[0] == "TCP") { ListViewItem listItem = new ListViewItem(); listItem.Text = infoList[i].ToString().Split(‘,‘)[0]; listItem.SubItems.Add(infoList[i].Split(‘,‘)[1]); listItem.SubItems.Add(infoList[i].Split(‘,‘)[2]); listItem.SubItems.Add(infoList[i].Split(‘,‘)[3]); listItem.SubItems.Add(infoList[i].Split(‘,‘)[4]); //int pid = Convert.ToInt32(infoList[i].Split(‘,‘)[4]); //listItem.SubItems.Add(GetFullPathByPid(pid)); listItem.SubItems.Add(nameList[i]); this.listView1.Items.Add(listItem); } else if (infoList[i].ToString().Split(‘,‘)[0] == "UDP") { ListViewItem listItem = new ListViewItem(); listItem.Text = infoList[i].ToString().Split(‘,‘)[0]; listItem.SubItems.Add(infoList[i].Split(‘,‘)[1]); listItem.SubItems.Add(infoList[i].Split(‘,‘)[2]); listItem.SubItems.Add(""); listItem.SubItems.Add(infoList[i].Split(‘,‘)[3]); //int pid = Convert.ToInt32(infoList[i].Split(‘,‘)[3]); //listItem.SubItems.Add(GetFullPathByPid(pid)); listItem.SubItems.Add(nameList[i]); this.listView1.Items.Add(listItem); } } } private string GetFullPathByPid(Int32 pid) { Int32 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, false, pid); char[] buf = new char[512]; UInt32 len = 512; QueryFullProcessImageNameW(hProcess, 0, buf, ref len); CloseHandle(hProcess); string nameList = new string(buf, 0, (int)len); return nameList; } private void Form1_KeyDown(object sender, KeyEventArgs e) { if (e.KeyValue == 116) { listView1.Items.Clear(); ShowInfo(); } } } }
效果图:
标签:
c#调用CMD、c#根据根据PID获取程序名