根据pid获取端口号
时间: 2024-02-23 14:59:22 浏览: 110
在 Windows 操作系统中,可以使用 WMI 查询获取进程的详细信息,包括 PID 和端口号。以下是一个示例代码,根据进程的 PID 获取端口号:
```csharp
using System;
using System.Management;
class Program
{
static void Main(string[] args)
{
// 要查询的进程 PID
int pid = 1234;
// 使用 WMI 查询获取进程的详细信息
ManagementObjectSearcher searcher = new ManagementObjectSearcher(
"SELECT * FROM Win32_Process WHERE ProcessId = " + pid);
ManagementObjectCollection results = searcher.Get();
// 遍历查询结果,获取端口号
foreach (ManagementObject result in results)
{
// 获取进程的句柄
uint processId = (uint)result["ProcessId"];
IntPtr handle = NativeMethods.OpenProcess(
NativeMethods.PROCESS_QUERY_INFORMATION | NativeMethods.PROCESS_VM_READ,
false, (int)processId);
// 获取进程的模块信息
NativeMethods.EnumProcessModules(handle, out IntPtr moduleHandle,
sizeof(IntPtr), out uint neededSize);
string moduleName = new string(' ', 1024);
NativeMethods.GetModuleFileNameEx(handle, moduleHandle, moduleName,
(uint)moduleName.Length);
// 获取进程监听的端口号
TcpTable tcpTable = new TcpTable();
uint tcpTableLength = (uint)Marshal.SizeOf(tcpTable);
NativeMethods.GetExtendedTcpTable(tcpTable, ref tcpTableLength, true,
NativeMethods.AF_INET, NativeMethods.TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL);
foreach (TcpRow row in tcpTable.rows)
{
if (row.owningPid == pid && row.state == TcpState.Listen)
{
Console.WriteLine("Process {0} listens on port {1}", moduleName, row.localPort);
}
}
// 关闭进程句柄
NativeMethods.CloseHandle(handle);
}
}
}
class NativeMethods
{
public const uint PROCESS_QUERY_INFORMATION = 0x0400;
public const uint PROCESS_VM_READ = 0x0010;
public const int AF_INET = 2;
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("psapi.dll", SetLastError = true)]
public static extern bool EnumProcessModules(IntPtr hProcess, out IntPtr lphModule, int cb, out uint lpcbNeeded);
[DllImport("psapi.dll", CharSet = CharSet.Unicode)]
public static extern uint GetModuleFileNameEx(IntPtr hProcess, IntPtr hModule, [Out] StringBuilder lpBaseName, uint nSize);
[DllImport("iphlpapi.dll", SetLastError = true)]
public static extern int GetExtendedTcpTable(IntPtr pTcpTable, ref uint pdwSize, bool bOrder, int ulAf, TCP_TABLE_CLASS TableClass, uint Reserved = 0);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(IntPtr hObject);
public enum TCP_TABLE_CLASS
{
TCP_TABLE_BASIC_LISTENER,
TCP_TABLE_BASIC_CONNECTIONS,
TCP_TABLE_BASIC_ALL,
TCP_TABLE_OWNER_PID_LISTENER,
TCP_TABLE_OWNER_PID_CONNECTIONS,
TCP_TABLE_OWNER_PID_ALL,
TCP_TABLE_OWNER_MODULE_LISTENER,
TCP_TABLE_OWNER_MODULE_CONNECTIONS,
TCP_TABLE_OWNER_MODULE_ALL
}
[StructLayout(LayoutKind.Sequential)]
public struct MIB_TCPROW_OWNER_PID
{
public uint state;
public uint localAddr;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] localPort;
public uint remoteAddr;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] remotePort;
public uint owningPid;
}
[StructLayout(LayoutKind.Sequential)]
public struct TcpTable
{
public uint rowsCount;
public MIB_TCPROW_OWNER_PID[] rows;
}
public enum TcpState
{
Closed = 1,
Listen = 2,
SynSent = 3,
SynReceived = 4,
Established = 5,
FinWait1 = 6,
FinWait2 = 7,
CloseWait = 8,
Closing = 9,
LastAck = 10,
TimeWait = 11,
DeleteTcb = 12
}
[StructLayout(LayoutKind.Sequential)]
public struct TcpRow
{
public uint state;
public uint localAddr;
public uint localPort;
public uint remoteAddr;
public uint remotePort;
public uint owningPid;
}
}
```
在上面的代码中,我们首先定义了要查询的进程 PID,然后使用 WMI 查询获取进程的详细信息。接着遍历查询结果,获取进程的模块信息和监听的端口号。具体实现过程中使用了一些 Windows API 函数和结构体,如 OpenProcess、EnumProcessModules、GetModuleFileNameEx、GetExtendedTcpTable 等。获取端口号的核心代码是调用 GetExtendedTcpTable 函数获取进程的 TCP 连接信息,然后从中筛选出监听中的 TCP 连接,从而得到端口号。
阅读全文