Delphi, How to get all local IPs?

前端 未结 6 1655
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-03 07:47

Any one know a way in delphi get a simple list (eg tstrings) of the local ip address.

I have had a look at the other related question, and cant seem to get my head a

相关标签:
6条回答
  • 2020-12-03 08:12

    From Delphi 7 Indy 9 source I find something that solved the problem using GStack. It's a little bit different from previous post.

    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;
    

    I think this will work with Indy 10 too.

    0 讨论(0)
  • 2020-12-03 08:17

    If you are using ICS for socket communication, you can use LocalIPList function, defined in the OverbyteIcsWSocket unit.

    Even if you are not using it, you can download the source code and look up the implementation. It uses WinSock internally.

    0 讨论(0)
  • 2020-12-03 08:17

    The Jedi Code Library contains a procedure

    procedure GetIpAddresses(Results: TStrings); 
    

    in unit JclSysInfo

    0 讨论(0)
  • 2020-12-03 08:19

    in indy 9, there is a unit IdStack, with the class 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;
    

    works great :)

    from Remy Lebeau's Comment

    The same exists in Indy 10, but the code is a little different:

    TIdStack.IncUsage; 
    try 
      GStack.AddLocalAddressesToList(ComboBox1.Items); 
      Edit.Caption := ComboBox1.Items[0]; 
    finally 
      TIdStack.DecUsage; 
    end; 
    
    0 讨论(0)
  • 2020-12-03 08:22

    I posted a solution on SO here. This will populate an array of records full of information for every adapter on the system. This includes the IP Address, but also includes MAC address, subnet mask, transferred/recvd packets, description, etc.

    Once you've populated the array of records, just enumerate it for the IP Addresses, if that's all you want.

    This emulates "ifconfig -a" on 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
    

    Here is the full source of the "ifconfig -a" project. You will also need to grab my helper unit (uAdapterInfo) and include it with this program.

    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.
    

    And here is the helper unit you need to include:

    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 讨论(0)
  • 2020-12-03 08:23

    It can also be done by using WinApi (necessary headers are in the Jedi ApiLib). This is how I do it in my TSAdminEx application:

    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;
    
    0 讨论(0)
提交回复
热议问题