windows - Hvilket PID lytter på en given port i c #

Indlæg af Hanne Mølgaard Plasc

Problem



Hvad er den nemmeste måde at få et PID, der lytter til en given port i C #?
I grund og grund vil jeg sørge for, at min tjeneste kører og lytter på en port, jeg har givet den.
Hvis der er en nemmere måde end at analysere netstat-output, bliver det godt.

Bedste reference


fra win XP SP2 og fremefter kan du P/Invoke til GetExtendedTcpTable [2]


Brug af denne persons skønne arbejde for at kvæle signaturen (PInvoke.net-spec er ufuldstændig) her er en (grov og dårlig ved fejlkontrol) eksempel [3]


using System;
using System.Runtime.InteropServices;

public enum TCP\_TABLE\_CLASS : int
{
    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;
    public byte localPort1;
    public byte localPort2;
    public byte localPort3;
    public byte localPort4;
    public uint remoteAddr;
    public byte remotePort1;
    public byte remotePort2;
    public byte remotePort3;
    public byte remotePort4;
    public int owningPid;

    public ushort LocalPort
{
        get
        {
            return BitConverter.ToUInt16(
                new byte[2] { localPort2, localPort1}, 0);
        }
    }

    public ushort RemotePort
    {
        get
        {
            return BitConverter.ToUInt16(
                new byte[2] { remotePort2, remotePort1}, 0);
        }
    }
}

[StructLayout(LayoutKind.Sequential)]
public struct MIB\_TCPTABLE\_OWNER\_PID
{
    public uint dwNumEntries;
    MIB\_TCPROW\_OWNER\_PID table;
}

[DllImport("iphlpapi.dll", SetLastError=true)]
static extern uint GetExtendedTcpTable(IntPtr pTcpTable, 
    ref int dwOutBufLen, 
    bool sort, 
    int ipVersion, 
    TCP\_TABLE\_CLASS tblClass,
    int reserved);

public static MIB\_TCPROW\_OWNER\_PID[] GetAllTcpConnections()
{
    MIB\_TCPROW\_OWNER\_PID[] tTable;
    int AF\_INET = 2;    // IP\_v4
    int buffSize = 0;

    // how much memory do we need?
    uint ret = GetExtendedTcpTable(IntPtr.Zero, 
        ref buffSize, 
        true, 
        AF\_INET, 
        TCP\_TABLE\_CLASS.TCP\_TABLE\_OWNER\_PID\_ALL,
        0);        
    if (ret != 0 && ret != 122) // 122 insufficient buffer size
        throw new Exception("bad ret on check " + ret);
    IntPtr buffTable = Marshal.AllocHGlobal(buffSize);

    try
    {
        ret = GetExtendedTcpTable(buffTable, 
            ref buffSize, 
            true, 
            AF\_INET, 
            TCP\_TABLE\_CLASS.TCP\_TABLE\_OWNER\_PID\_ALL, 
            0);
        if (ret != 0)
            throw new Exception("bad ret "+ ret);        

        // get the number of entries in the table
        MIB\_TCPTABLE\_OWNER\_PID tab = 
            (MIB\_TCPTABLE\_OWNER\_PID)Marshal.PtrToStructure(
                buffTable, 
                typeof(MIB\_TCPTABLE\_OWNER\_PID));
         IntPtr rowPtr = (IntPtr)((long)buffTable + 
             Marshal.SizeOf(tab.dwNumEntries));
        tTable = new MIB\_TCPROW\_OWNER\_PID[tab.dwNumEntries];

        for (int i = 0; i < tab.dwNumEntries; i++)
        {
            MIB\_TCPROW\_OWNER\_PID tcpRow = (MIB\_TCPROW\_OWNER\_PID)Marshal
                .PtrToStructure(rowPtr, typeof(MIB\_TCPROW\_OWNER\_PID));
            tTable[i] = tcpRow;
            // next entry
            rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(tcpRow));   
        }
    }
    finally
    {
        // Free the Memory
        Marshal.FreeHGlobal(buffTable);
    }
    return tTable;
}

Andre referencer 1


tjek dette projekt:
http://www.codeproject.com/KB/IP/iphlpapi.aspx[4]


Det bruger Interop i C # for at komme til den underliggende GetTcpTable Win API-funktion. Og derfor kan du give den proces id du søger.


håber det hjælper,
Alex