Delphi, ¿cómo obtener todos los IP locales?
winsock (6)
Cualquiera sabe cómo en Delphi obtener una lista simple (por ejemplo, tstrings) de la dirección ip local.
He echado un vistazo a la otra pregunta relacionada, y no puedo entender cómo convertirlos a Delphi.
Si está utilizando ICS para comunicación de socket, puede usar la función LocalIPList, definida en la unidad OverbyteIcsWSocket.
Incluso si no lo está usando, puede descargar el código fuente y buscar la implementación. Utiliza WinSock internamente.
en indy 9, hay una unidad IdStack, con la clase 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;
Funciona genial :)
del comentario de Remy Lebeau
Lo mismo existe en Indy 10, pero el código es un poco diferente:
TIdStack.IncUsage;
try
GStack.AddLocalAddressesToList(ComboBox1.Items);
Edit.Caption := ComboBox1.Items[0];
finally
TIdStack.DecUsage;
end;
También se puede hacer usando WinApi (los encabezados necesarios están en Jedi ApiLib). Así es como lo hago en mi aplicación TSAdminEx :
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;
La Biblioteca del Código Jedi contiene un procedimiento
procedure GetIpAddresses(Results: TStrings);
en la unidad JclSysInfo
De la fuente Delphi 7 Indy 9 encuentro algo que resolvió el problema usando GStack
. Es un poco diferente de la publicación anterior.
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;
Creo que esto también funcionará con Indy 10.
Publiqué una solución sobre SO aquí . Esto rellenará una matriz de registros llenos de información para cada adaptador en el sistema. Esto incluye la dirección IP, pero también incluye la dirección MAC, la máscara de subred, los paquetes transferidos / repetidos, la descripción, etc.
Una vez que haya completado la matriz de registros, simplemente enuémbrela para las direcciones IP, si eso es todo lo que desea.
Esto emula "ifconfig -a" en 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
Aquí está la fuente completa del proyecto "ifconfig -a". También necesitarás tomar mi unidad auxiliar (uAdapterInfo) e incluirla en este programa.
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.
Y aquí está la unidad auxiliar que debes incluir:
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.