2009-02-23 20 views
16

Chiunque conosca un modo in delphi ottiene una lista semplice (es. Tstrings) dell'indirizzo ip locale.Delphi, Come ottenere tutti gli IP locali?

Ho dato un'occhiata all'altra domanda correlata e non riesco a capire come convertire in delphi.

+0

Sarebbe utile se si collegasse già alle soluzioni di lavoro. Non stai chiedendo come ottenere un elenco di indirizzi IP; stai chiedendo come convertire un altro codice in Delphi. Quindi mostra il codice originale. –

+0

È alquanto complicato ... dipende da quali sistemi operativi dovrebbe funzionare il codice ... probabilmente è un buffer overflow/soggetto a crash. Fortunatamente gli OS-es di Windows hanno almeno un apis/supporto migliore per questo. –

risposta

14

a Indy 9, c'è un'unità IdStack, con la classe TIdStack

fStack := TIdStack.CreateStack; 
try 
    edit.caption := fStack.LocalAddress; //the first address i believe 
    ComboBox1.Items.Assign(fStack.LocalAddresses); //all the address' 
finally 
    freeandnil(fStack); 
end; 

grandi opere :)

dal Commento di Remy Lebeau

Lo stesso esiste in Indy 10, ma il codice è un po 'diverso:

TIdStack.IncUsage; 
try 
    GStack.AddLocalAddressesToList(ComboBox1.Items); 
    Edit.Caption := ComboBox1.Items[0]; 
finally 
    TIdStack.DecUsage; 
end; 
+2

Lo stesso esiste in Indy 10, ma il codice è leggermente diverso: TIdStack.IncUsage; try GStack.AddLocalAddressesToList (ComboBox1.Items); Edit.Caption: = ComboBox1.Items [0]; infine TIdStack.DecUsage; fine; –

+0

@RemyLebeau Sto provando questo con Indy 10 in XE2 senza fortuna (usando sia 'TStringList' che' TStrings' - Sto ricevendo 'Abstract Error' solo quando si chiama' AddLocalAddressesToList (L); ' –

+0

Strano come l'abstract di quella procedura dove è dichiarato: 'procedura AddLocalAddressesToList (AAddresses: TStrings); virtuale; abstract;' –

8

Se si utilizza ICS per la comunicazione socket, è possibile utilizzare la funzione LocalIPList, definita nell'unità OverbyteIcsWSocket.

Anche se non lo si utilizza, è possibile scaricare il codice sorgente e cercare l'implementazione. Usa WinSock internamente.

+0

grazie, mi hai dato il suggerimento di cui avevo bisogno, sto usando indy9 così ho fatto un ficcanaso e ho trovato la mia risposta :) –

4

Ho inviato un solution on SO here. Questo popolerà una serie di record pieni di informazioni per ogni adattatore sul sistema. Ciò include l'indirizzo IP, ma include anche indirizzo MAC, subnet mask, pacchetti trasferiti/recvd, descrizione, ecc.

Dopo aver compilato l'array di record, è sufficiente elencarlo per gli indirizzi IP, se questo è tutto volere.

Questo emula "ifconfig -a" su Linux:

C:\>ifconfig 
0x00000001 
"MS TCP Loopback interface" 
     Link encap: Local loopback 
     inet addr:127.0.0.1 Mask: 255.0.0.0 
     MTU: 1520 Speed:10.00 Mbps 
     Admin status:UP Oper status:OPERATIONAL 
     RX packets:179805 dropped:0 errors:0 unkown:0 
     TX packets:179804 dropped:0 errors:0 txqueuelen:0 

0x00000002 
"Broadcom NetXtreme 57xx Gigabit Controller - Packet Scheduler Miniport" 
     Link encap: Ethernet HWaddr: XX-XX-XX-XX-XX-XX 
     inet addr:10.101.101.102 Mask: 255.255.255.0 
     MTU: 1500 Speed:100.00 Mbps 
     Admin status:UP Oper status:OPERATIONAL 
     RX packets:6287896 dropped:0 errors:0 unkown:0 
     TX packets:5337100 dropped:0 errors:1 txqueuelen:0 

Ecco il sorgente completo del progetto "ifconfig -a". Avrai anche bisogno di grab my helper unit (uAdapterInfo) e includilo con questo programma.

program ifconfig; 

{$APPTYPE CONSOLE} 

uses 
    SysUtils, 
    Classes, 
    Winsock, 
    uAdapterInfo in 'uAdapterInfo.pas'; 

type 
    TAdapterInfo = array of record 
    dwIndex: longint; 
    dwType:  longint; 
    dwMtu:  longint; 
    dwSpeed: extended; 
    dwPhysAddrLen: longint; 
    bPhysAddr: string; 
    dwAdminStatus: longint; 
    dwOperStatus: longint; 
    dwLastChange: longint; 
    dwInOctets: longint; 
    dwInUcastPkts: longint; 
    dwInNUcastPkts: longint; 
    dwInDiscards: longint; 
    dwInErrors: longint; 
    dwInUnknownProtos: longint; 
    dwOutOctets: longint; 
    dwOutUcastPkts: longint; 
    dwOutNUcastPkts: longint; 
    dwOutDiscards: longint; 
    dwOutErrors: longint; 
    dwOutQLen: longint; 
    dwDescrLen: longint; 
    bDescr:  string; 
    sIpAddress: string; 
    sIpMask: string; 
    end; 




    function Get_EthernetAdapterDetail(var AdapterDataFound: TAdapterInfo): boolean; 
    var 
    pIfTable: ^_IfTable; 
    pIpTable: ^_IpAddrTable; 
    ifTableSize, ipTableSize: longint; 
    tmp:  string; 
    i, j, k, m: integer; 
    ErrCode: longint; 
    sAddr, sMask: in_addr; 
    IPAddresses, IPMasks: TStringList; 
    sIPAddressLine, sIPMaskLine: string; 
    bResult: boolean; 
    begin 
    bResult := True; //default return value 
    pIfTable := nil; 
    pIpTable := nil; 

    IPAddresses := TStringList.Create; 
    IPMasks  := TStringList.Create; 

    try 
     // First: just get the buffer size. 
     // TableSize returns the size needed. 
     ifTableSize := 0; // Set to zero so the GetIfTabel function 
     // won't try to fill the buffer yet, 
     // but only return the actual size it needs. 
     GetIfTable(pIfTable, ifTableSize, 1); 
     if (ifTableSize < SizeOf(MIB_IFROW) + Sizeof(longint)) then 
     begin 
     bResult := False; 
     Result := bResult; 
     Exit; // less than 1 table entry?! 
     end; 

     ipTableSize := 0; 
     GetIpAddrTable(pIpTable, ipTableSize, 1); 
     if (ipTableSize < SizeOf(MIB_IPADDRROW) + Sizeof(longint)) then 
     begin 
     bResult := False; 
     Result := bResult; 
     Exit; // less than 1 table entry?! 
     end; 

     // Second: 
     // allocate memory for the buffer and retrieve the 
     // entire table. 
     GetMem(pIfTable, ifTableSize); 
     ErrCode := GetIfTable(pIfTable, ifTableSize, 1); 

     if ErrCode <> ERROR_SUCCESS then 
     begin 
     bResult := False; 
     Result := bResult; 
     Exit; // OK, that did not work. 
     // Not enough memory i guess. 
     end; 

     GetMem(pIpTable, ipTableSize); 
     ErrCode := GetIpAddrTable(pIpTable, ipTableSize, 1); 

     if ErrCode <> ERROR_SUCCESS then 
     begin 
     bResult := False; 
     Result := bResult; 
     Exit; 
     end; 

     for k := 1 to pIpTable^.dwNumEntries do 
     begin 
     sAddr.S_addr := pIpTable^.table[k].dwAddr; 
     sMask.S_addr := pIpTable^.table[k].dwMask; 

     sIPAddressLine := Format('0x%8.8x', [(pIpTable^.table[k].dwIndex)]) + 
      '=' + Format('%s', [inet_ntoa(sAddr)]); 
     sIPMaskLine := Format('0x%8.8x', [(pIpTable^.table[k].dwIndex)]) + 
      '=' + Format('%s', [inet_ntoa(sMask)]); 

     IPAddresses.Add(sIPAddressLine); 
     IPMasks.Add(sIPMaskLine); 
     end; 

     SetLength(AdapterDataFound, pIfTable^.nRows); //initialize the array or records 
     for i := 1 to pIfTable^.nRows do 
     try 
      //if pIfTable^.ifRow[i].dwType=MIB_IF_TYPE_ETHERNET then 
      //begin 
      m := i - 1; 
      AdapterDataFound[m].dwIndex := 4;//(pIfTable^.ifRow[i].dwIndex); 
      AdapterDataFound[m].dwType := (pIfTable^.ifRow[i].dwType); 
      AdapterDataFound[m].dwIndex := (pIfTable^.ifRow[i].dwIndex); 
      AdapterDataFound[m].sIpAddress := 
      IPAddresses.Values[Format('0x%8.8x', [(pIfTable^.ifRow[i].dwIndex)])]; 
      AdapterDataFound[m].sIpMask := 
      IPMasks.Values[Format('0x%8.8x', [(pIfTable^.ifRow[i].dwIndex)])]; 
      AdapterDataFound[m].dwMtu := (pIfTable^.ifRow[i].dwMtu); 
      AdapterDataFound[m].dwSpeed := (pIfTable^.ifRow[i].dwSpeed); 
      AdapterDataFound[m].dwAdminStatus := (pIfTable^.ifRow[i].dwAdminStatus); 
      AdapterDataFound[m].dwOperStatus := (pIfTable^.ifRow[i].dwOperStatus); 
      AdapterDataFound[m].dwInUcastPkts := (pIfTable^.ifRow[i].dwInUcastPkts); 
      AdapterDataFound[m].dwInNUcastPkts := (pIfTable^.ifRow[i].dwInNUcastPkts); 
      AdapterDataFound[m].dwInDiscards := (pIfTable^.ifRow[i].dwInDiscards); 
      AdapterDataFound[m].dwInErrors := (pIfTable^.ifRow[i].dwInErrors); 
      AdapterDataFound[m].dwInUnknownProtos := (pIfTable^.ifRow[i].dwInUnknownProtos); 
      AdapterDataFound[m].dwOutNUcastPkts := (pIfTable^.ifRow[i].dwOutNUcastPkts); 
      AdapterDataFound[m].dwOutUcastPkts := (pIfTable^.ifRow[i].dwOutUcastPkts); 
      AdapterDataFound[m].dwOutDiscards := (pIfTable^.ifRow[i].dwOutDiscards); 
      AdapterDataFound[m].dwOutErrors := (pIfTable^.ifRow[i].dwOutErrors); 
      AdapterDataFound[m].dwOutQLen := (pIfTable^.ifRow[i].dwOutQLen); 
      AdapterDataFound[m].bDescr := (pIfTable^.ifRow[i].bDescr); 

      tmp := ''; 
      for j := 0 to pIfTable^.ifRow[i].dwPhysAddrLen - 1 do 
      begin 
      if Length(tmp) > 0 then 
       tmp := tmp + '-' + format('%.2x', [pIfTable^.ifRow[i].bPhysAddr[j]]) 
      else 
       tmp := tmp + format('%.2x', [pIfTable^.ifRow[i].bPhysAddr[j]]); 
      end; 

      if Length(tmp) > 0 then 
      begin 
      AdapterDataFound[m].bPhysAddr := tmp; 
      end; 
     except 
      bResult := False; 
      Result := bResult; 
      Exit; 
     end; 
    finally 
     if Assigned(pIfTable) then 
     begin 
     FreeMem(pIfTable, ifTableSize); 
     end; 

     FreeAndNil(IPMasks); 
     FreeAndNil(IPAddresses); 
    end; 

    Result := bResult; 
    end; 



var 
    AdapterData: TAdapterInfo; 
    i: integer; 
begin 
    try 
    WriteLn(''); 
    if Get_EthernetAdapterDetail(AdapterData) then 
    begin 
     for i := 0 to Length(AdapterData) - 1 do 
     begin 
     WriteLn(Format('0x%8.8x', [AdapterData[i].dwIndex])); 
     WriteLn('"' + AdapterData[i].bDescr + '"'); 
     Write(Format(#9 + 'Link encap: %s ', [Get_if_type(AdapterData[i].dwType)])); 

     if Length(AdapterData[i].bPhysAddr) > 0 then 
      Write('HWaddr: ' + AdapterData[i].bPhysAddr); 

     Write(#13 + #10 + #9 + 'inet addr:' + AdapterData[i].sIpAddress); 
     WriteLn(' Mask: ' + AdapterData[i].sIpMask); 
     WriteLn(Format(#9 + 'MTU: %d Speed:%.2f Mbps', [AdapterData[i].dwMtu, 
      (AdapterData[i].dwSpeed)/1000/1000])); 
     Write(#9 + 'Admin status:' + Get_if_admin_status(AdapterData[i].dwAdminStatus)); 
     WriteLn(' Oper status:' + Get_if_oper_status(AdapterData[i].dwOperStatus)); 
     WriteLn(#9 + Format('RX packets:%d dropped:%d errors:%d unkown:%d', 
      [AdapterData[i].dwInUcastPkts + AdapterData[i].dwInNUcastPkts, 
      AdapterData[i].dwInDiscards, AdapterData[i].dwInErrors, 
      AdapterData[i].dwInUnknownProtos])); 
     WriteLn(#9 + Format('TX packets:%d dropped:%d errors:%d txqueuelen:%d', 
      [AdapterData[i].dwOutUcastPkts + AdapterData[i].dwOutNUcastPkts, 
      AdapterData[i].dwOutDiscards, AdapterData[i].dwOutErrors, 
      AdapterData[i].dwOutQLen])); 

     WriteLn(''); 
     end; 
    end 
    else 
    begin 
     WriteLn(#13+#10+'*** Error retrieving adapter information'); 
    end; 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
end. 

E qui è l'unità di supporto è necessario includere:

unit uAdapterInfo; 

interface 

uses 
    Classes, 
    SysUtils; 

const 
    MAX_INTERFACE_NAME_LEN = $100; 
    ERROR_SUCCESS = 0; 
    MAXLEN_IFDESCR = $100; 
    MAXLEN_PHYSADDR = 8; 

    MIB_IF_OPER_STATUS_NON_OPERATIONAL = 0; 
    MIB_IF_OPER_STATUS_UNREACHABLE = 1; 
    MIB_IF_OPER_STATUS_DISCONNECTED = 2; 
    MIB_IF_OPER_STATUS_CONNECTING = 3; 
    MIB_IF_OPER_STATUS_CONNECTED = 4; 
    MIB_IF_OPER_STATUS_OPERATIONAL = 5; 

    MIB_IF_TYPE_OTHER = 1; 
    MIB_IF_TYPE_ETHERNET = 6; 
    MIB_IF_TYPE_TOKENRING = 9; 
    MIB_IF_TYPE_FDDI  = 15; 
    MIB_IF_TYPE_PPP  = 23; 
    MIB_IF_TYPE_LOOPBACK = 24; 
    MIB_IF_TYPE_SLIP  = 28; 

    MIB_IF_ADMIN_STATUS_UP  = 1; 
    MIB_IF_ADMIN_STATUS_DOWN = 2; 
    MIB_IF_ADMIN_STATUS_TESTING = 3; 

    _MAX_ROWS_ = 20; 
    ANY_SIZE = 1; 


type 
    MIB_IFROW = record 
    wszName: array[0 .. (MAX_INTERFACE_NAME_LEN * 2 - 1)] of ansichar; 
    dwIndex: longint; 
    dwType:  longint; 
    dwMtu:  longint; 
    dwSpeed: longint; 
    dwPhysAddrLen: longint; 
    bPhysAddr: array[0 .. (MAXLEN_PHYSADDR - 1)] of byte; 
    dwAdminStatus: longint; 
    dwOperStatus: longint; 
    dwLastChange: longint; 
    dwInOctets: longint; 
    dwInUcastPkts: longint; 
    dwInNUcastPkts: longint; 
    dwInDiscards: longint; 
    dwInErrors: longint; 
    dwInUnknownProtos: longint; 
    dwOutOctets: longint; 
    dwOutUcastPkts: longint; 
    dwOutNUcastPkts: longint; 
    dwOutDiscards: longint; 
    dwOutErrors: longint; 
    dwOutQLen: longint; 
    dwDescrLen: longint; 
    bDescr:  array[0 .. (MAXLEN_IFDESCR - 1)] of ansichar; 
    end; 

type 
    MIB_IPADDRROW = record 
    dwAddr:  longint; 
    dwIndex:  longint; 
    dwMask:  longint; 
    dwBCastAddr: longint; 
    dwReasmSize: longint; 
    unused1:  word; 
    unused2:  word; 
    end; 

type 
    _IfTable = record 
    nRows: longint; 
    ifRow: array[1.._MAX_ROWS_] of MIB_IFROW; 
    end; 

type 
    _IpAddrTable = record 
    dwNumEntries: longint; 
    table: array[1..ANY_SIZE] of MIB_IPADDRROW; 
    end; 



function GetIfTable(pIfTable: Pointer; var pdwSize: longint; bOrder: longint): longint; 
    stdcall; 
function GetIpAddrTable(pIpAddrTable: Pointer; var pdwSize: longint; 
    bOrder: longint): longint; stdcall; 

function Get_if_type(iType: integer): string; 
function Get_if_admin_status(iStatus: integer): string; 
function Get_if_oper_status(iStatus: integer): string; 


implementation 

function GetIfTable; stdcall; external 'IPHLPAPI.DLL'; 
function GetIpAddrTable; stdcall; external 'IPHLPAPI.DLL'; 

function Get_if_type(iType: integer): string; 
var 
    sResult: string; 
begin 
    sResult := 'UNKNOWN'; 
    case iType of 
    1: sResult := 'Other'; 
    6: sResult := 'Ethernet'; 
    9: sResult := 'Tokenring'; 
    15: sResult := 'FDDI'; 
    23: sResult := 'PPP'; 
    24: sResult := 'Local loopback'; 
    28: sResult := 'SLIP'; 
    37: sResult := 'ATM'; 
    71: sResult := 'IEEE 802.11'; 
    131: sResult := 'Tunnel'; 
    144: sResult := 'IEEE 1394 (Firewire)'; 
    end; 

    Result := sResult; 
end; 

function Get_if_admin_status(iStatus: integer): string; 
var 
    sResult: string; 
begin 
    sResult := 'UNKNOWN'; 

    case iStatus of 
    1: sResult := 'UP'; 
    2: sResult := 'DOWN'; 
    3: sResult := 'TESTING'; 
    end; 

    Result := sResult; 
end; 

function Get_if_oper_status(iStatus: integer): string; 
var 
    sResult: string; 
begin 
    sResult := 'UNKNOWN'; 

    case iStatus of 
    0: sResult := 'NON_OPERATIONAL'; 
    1: sResult := 'UNREACHABLE'; 
    2: sResult := 'DISCONNECTED'; 
    3: sResult := 'CONNECTING'; 
    4: sResult := 'CONNECTED'; 
    5: sResult := 'OPERATIONAL'; 
    end; 

    Result := sResult; 
end; 

end. 
+0

Sembra che il tuo codice sopra non sia completo. La risposta a cui si collega ha circa il doppio del codice. –

+0

@Mick - Il codice si arresta in modo anomalo su questa riga (errore di verifica intervallo): per k: = 1 a pIpTable^.dwNumEntries do – Ampere

+0

Questa riga ha causato per me errore di violazione di accesso: tmp: = tmp + '-' + format ('% .2x ', [pIfTable^.ifRow [i] .bPhysAddr [j]]) Poiché j è derivato da dwPhysAddrLen che aveva il valore 3211316 mentre l'array bPhysAddr aveva solo celle 0-7 – SolarBrian

2

può essere fatto anche utilizzando Winapi (connettori necessari siano presenti Jedi ApiLib). Questo è come lo faccio nel mio TSAdminEx applicazione:

function EnumerateIpAddresses(var IPList: TStringList): Boolean; 
var 
    IPAddrTable: PMIB_IPADDRTABLE; 
    Size: DWORD; 
    Res: DWORD; 
    Index: Integer; 
    Addr: IN_ADDR; 
begin 
    Result := False; 

    IPList.Duplicates := dupIgnore; 

    Size := 0; 
    // Get required Size 
    if GetIpAddrTable(nil, Size, False) <> ERROR_INSUFFICIENT_BUFFER then Exit; 

    // Reserve mem 
    GetMem(IPAddrTable, Size); 
    Res := GetIpAddrTable(IPAddrTable, Size, True); 

    if Res <> NO_ERROR then Exit; 

    for Index := 0 to IPAddrTable^.dwNumEntries-1 do 
    begin 
    // Convert ADDR to String and add to IPList 
    Addr.S_addr := IPAddrTable^.table[Index].dwAddr; 
    // Prevent implicit string conversion warning in D2009 by explicit cast to string 
    IPList.Add({$IFDEF UNICODE}String({$ENDIF UNICODE}inet_ntoa(Addr){$IFDEF UNICODE}){$ENDIF UNICODE}); 
    end; 

    // Free Mem 
    FreeMem(IPAddrTable); 

    Result := True; 
end; 
3

Il Codice Biblioteca Jedi contiene una procedura

procedure GetIpAddresses(Results: TStrings); 

nell'unità JclSysInfo

1

Da Delphi 7 Indy 9 fonte trovo qualcosa che risolto il problema usando GStack. È un po 'diverso dal post precedente.

function GetLocalIPAddress(List: TStringlist): Integer; 
begin  
    if Assigned(GStack) then 
    List.Assign(TStringlist(GStack.LocalAddresses)) 
    else 
    begin 
    GStack := GStackClass.Create; 
    List.Assing(TStringlist(GStack.LocalAddresses)); 
    FreeAndNil(GStack); 
    end; 
end; 

Penso che questo funzionerà anche con Indy 10.

Problemi correlati