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獲取程序名
