2009-02-23 47 views
16

Bất kỳ ai biết một cách trong delphi có được một danh sách đơn giản (ví dụ như tstrings) của địa chỉ ip địa phương.Delphi, Cách nhận tất cả các IP địa phương?

Tôi đã xem xét câu hỏi liên quan khác và dường như không thể xoay quanh việc chuyển đổi chúng thành delphi.

+0

Sẽ hữu ích nếu bạn liên kết đến các giải pháp làm việc. Bạn không hỏi cách lấy danh sách địa chỉ IP; bạn đang hỏi cách chuyển đổi mã khác thành Delphi. Vì vậy, hiển thị mã ban đầu. –

+0

Đó là khó khăn nhất ... phụ thuộc vào hệ điều hành mã nên làm việc trên ... nó có thể tràn bộ đệm/tai nạn dễ bị. May mắn thay sau này os-es của windows ít nhất có apis tốt hơn/hỗ trợ cho việc này. –

Trả lời

14

trong indy 9, có một đơn vị IdStack, với lớp 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; 

hoạt động :) lớn

từ Remy Lebeau's Comment

Cùng tồn tại trong Indy 10, nhưng mã là một chút khác nhau:

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

Cùng tồn tại trong Indy 10, nhưng mã có một chút khác biệt: TIdStack.IncUsage; thử GStack.AddLocalAddressesToList (ComboBox1.Items); Edit.Caption: = ComboBox1.Items [0]; cuối cùng là TIdStack.DecUsage; kết thúc; –

+0

@RemyLebeau Tôi đang cố gắng này với Indy 10 trong XE2 không có may mắn (sử dụng cả 'TStringList' và' TStrings' - tôi nhận được 'Tóm tắt lỗi' chỉ khi gọi' AddLocalAddressesToList (L); ' –

+0

Lạ cách trừu tượng của thủ tục đó nơi nó được khai báo: 'procedure AddLocalAddressesToList (AAddresses: TStrings); virtual; abstract;' –

8

Nếu bạn đang sử dụng ICS cho giao tiếp socket, bạn có thể sử dụng chức năng LocalIPList, được định nghĩa trong đơn vị OverbyteIcsWSocket.

Thậm chí nếu bạn không sử dụng, bạn có thể tải xuống mã nguồn và tra cứu triển khai. Nó sử dụng WinSock trong nội bộ.

+0

thankyou, bạn đã cho tôi gợi ý tôi cần, im sử dụng indy9 vì vậy tôi đã có một snoop xung quanh đó và tìm thấy câu trả lời của tôi :) –

4

Tôi đã đăng solution on SO here. Điều này sẽ điền một mảng các bản ghi đầy đủ thông tin cho mỗi bộ điều hợp trên hệ thống. Điều này bao gồm Địa chỉ IP, nhưng cũng bao gồm địa chỉ MAC, mặt nạ mạng con, các gói chuyển tiếp/recvd, mô tả, v.v.

Khi bạn đã điền vào các bản ghi, chỉ cần liệt kê nó cho các Địa chỉ IP, nếu đó là tất cả các bạn muốn.

này mô phỏng "ifconfig -a" trên 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 

Đây là nguồn gốc đầy đủ của dự án "ifconfig -a". Bạn cũng sẽ cần phải grab my helper unit (uAdapterInfo) và bao gồm nó với chương trình này.

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. 

Và đây là đơn vị helper bạn cần bao gồm:

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

Có vẻ như mã trên của bạn chưa hoàn thành. Câu trả lời bạn liên kết đến có nhiều gấp đôi mã. –

+0

@Mick - Bạn mã lỗi trên dòng này (phạm vi kiểm tra lỗi): cho k: = 1 đến pIpTable^.dwNumEntries do – Ampere

+0

Dòng này gây ra lỗi vi phạm eaccess cho tôi: tmp: = tmp + '-' + format ('% .2x ', [pIfTable^.ifRow [i] .bPhysAddr [j]]) Vì j có nguồn gốc từ dwPhysAddrLen có giá trị 3211316 trong khi mảng bPhysAddr chỉ có các ô 0-7 – SolarBrian

2

Nó cũng có thể được thực hiện bằng cách sử dụng WinAPI (tiêu đề cần thiết là trong Jedi ApiLib). Đây là cách tôi làm điều đó trong TSAdminEx ứng dụng của tôi:

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

Các Jedi Thư Viện Mã chứa một thủ tục

procedure GetIpAddresses(Results: TStrings); 

trong đơn vị JclSysInfo

1

Từ Delphi 7 Indy 9 nguồn tôi thấy cái gì mà giải quyết sự cố khi sử dụng GStack. Nó hơi khác một chút so với bài trước.

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; 

Tôi nghĩ điều này cũng sẽ hoạt động với Indy 10.

Các vấn đề liên quan