まずこれらのIPヘルパAPIや構造体を定義します。
uses
Windows, SysUtils;
const
MAX_ADAPTER_DESCRIPTION_LENGTH = 128;
{$EXTERNALSYM MAX_ADAPTER_DESCRIPTION_LENGTH}
MAX_ADAPTER_NAME_LENGTH = 256;
{$EXTERNALSYM MAX_ADAPTER_NAME_LENGTH}
MAX_ADAPTER_ADDRESS_LENGTH = 8;
{$EXTERNALSYM MAX_ADAPTER_ADDRESS_LENGTH}
MIB_IF_TYPE_OTHER = 1;
{$EXTERNALSYM MIB_IF_TYPE_OTHER}
MIB_IF_TYPE_ETHERNET = 6;
{$EXTERNALSYM MIB_IF_TYPE_ETHERNET}
MIB_IF_TYPE_TOKENRING = 9;
{$EXTERNALSYM MIB_IF_TYPE_TOKENRING}
MIB_IF_TYPE_FDDI = 15;
{$EXTERNALSYM MIB_IF_TYPE_FDDI}
MIB_IF_TYPE_PPP = 23;
{$EXTERNALSYM MIB_IF_TYPE_PPP}
MIB_IF_TYPE_LOOPBACK = 24;
{$EXTERNALSYM MIB_IF_TYPE_LOOPBACK}
MIB_IF_TYPE_SLIP = 28;
{$EXTERNALSYM MIB_IF_TYPE_SLIP}
type
time_t = Longint;
{$EXTERNALSYM time_t}
PIP_MASK_STRING = ^IP_MASK_STRING;
{$EXTERNALSYM PIP_MASK_STRING}
IP_ADDRESS_STRING = record
S: array [0..15] of AnsiChar;
end;
{$EXTERNALSYM IP_ADDRESS_STRING}
PIP_ADDRESS_STRING = ^IP_ADDRESS_STRING;
{$EXTERNALSYM PIP_ADDRESS_STRING}
IP_MASK_STRING = IP_ADDRESS_STRING;
{$EXTERNALSYM IP_MASK_STRING}
PIP_ADDR_STRING = ^IP_ADDR_STRING;
{$EXTERNALSYM PIP_ADDR_STRING}
_IP_ADDR_STRING = record
Next: PIP_ADDR_STRING;
IpAddress: IP_ADDRESS_STRING;
IpMask: IP_MASK_STRING;
Context: DWORD;
end;
{$EXTERNALSYM _IP_ADDR_STRING}
IP_ADDR_STRING = _IP_ADDR_STRING;
{$EXTERNALSYM IP_ADDR_STRING}
PIP_ADAPTER_INFO = ^IP_ADAPTER_INFO;
{$EXTERNALSYM PIP_ADAPTER_INFO}
_IP_ADAPTER_INFO = record
Next: PIP_ADAPTER_INFO;
ComboIndex: DWORD;
AdapterName: array [0..MAX_ADAPTER_NAME_LENGTH + 3] of AnsiChar;
Description: array [0..MAX_ADAPTER_DESCRIPTION_LENGTH + 3] of AnsiChar;
AddressLength: UINT;
Address: array [0..MAX_ADAPTER_ADDRESS_LENGTH - 1] of BYTE;
Index: DWORD;
Type_: UINT;
DhcpEnabled: UINT;
CurrentIpAddress: PIP_ADDR_STRING;
IpAddressList: IP_ADDR_STRING;
GatewayList: IP_ADDR_STRING;
DhcpServer: IP_ADDR_STRING;
HaveWins: BOOL;
PrimaryWinsServer: IP_ADDR_STRING;
SecondaryWinsServer: IP_ADDR_STRING;
LeaseObtained: time_t;
LeaseExpires: time_t;
end;
{$EXTERNALSYM _IP_ADAPTER_INFO}
IP_ADAPTER_INFO = _IP_ADAPTER_INFO;
{$EXTERNALSYM IP_ADAPTER_INFO}
function GetAdaptersInfo(pAdapterInfo: PIP_ADAPTER_INFO;
var pOutBufLen: ULONG): DWORD; stdcall;
external 'iphlpapi.dll' Name 'GetAdaptersInfo';
{$EXTERNALSYM GetAdaptersInfo}
そしてtype
TAdapterType = (atUnknown,
atOther,
atEthernet,
atTokenRing,
atFDDI,
atPPP,
atLoopback,
atSLIP,
atWLAN);
TEnumAdapterInfoFunc = function (const AdapterName: String;
const Description: String;
const HardwareAddress: String;
AdapterIndex: Integer;
AdapterType: TAdapterType;
DhcpEnabled: Boolean;
const IPAddress: String;
const Mask: String;
const Gateway: String;
const DHCPServer: String;
Data: Pointer): Boolean;
procedure EnumAdapterInfo(Func: TEnumAdapterInfoFunc; Data: Pointer);
function FormatHardwareAddress(Ptr: PIP_ADAPTER_INFO): String;
var
Index: Integer;
begin
Result := '';
for Index := 0 to Ptr^.AddressLength - 1 do
begin
Result := Result + Format('%02.2X-',[Ptr^.Address[Index]]);
end;
if Result <> '' then
begin
Delete(Result,Length(Result),1);
end;
end;
var
pAdapterInfo: PIP_ADAPTER_INFO;
Ptr: PIP_ADAPTER_INFO;
pOutBufLen: ULONG;
RetVal: DWORD;
AdapterIndex: Integer;
AdapterName: String;
Description: String;
HardwareAddress: String;
AdapterType: TAdapterType;
IPAddress: String;
NetMask: String;
Gateway: String;
DHCPServer: String;
begin
pOutBufLen := SizeOf(IP_ADAPTER_INFO);
pAdapterInfo := AllocMem(pOutBufLen);
try
RetVal := GetAdaptersInfo(pAdapterInfo,pOutBufLen);
if RetVal = ERROR_BUFFER_OVERFLOW then
begin
FreeMem(pAdapterInfo);
pAdapterInfo := AllocMem(pOutBufLen);
RetVal := GetAdaptersInfo(pAdapterInfo,pOutBufLen);
end;
if RetVal <> NO_ERROR then
begin
Exit;
end;
Ptr := pAdapterInfo;
while Ptr <> nil do
begin
AdapterName := Trim(String(Ptr^.AdapterName));
Description := Trim(String(Ptr^.Description));
HardwareAddress := FormatHardwareAddress(Ptr);
AdapterIndex := Ptr^.Index;
case Ptr^.Type_ of
MIB_IF_TYPE_OTHER:
begin
AdapterType := atOther;
end;
MIB_IF_TYPE_ETHERNET:
begin
AdapterType := atEthernet;
end;
MIB_IF_TYPE_TOKENRING:
begin
AdapterType := atTokenRing;
end;
MIB_IF_TYPE_FDDI:
begin
AdapterType := atFDDI;
end;
MIB_IF_TYPE_PPP:
begin
AdapterType := atPPP;
end;
MIB_IF_TYPE_LOOPBACK:
begin
AdapterType := atLoopback;
end;
MIB_IF_TYPE_SLIP:
begin
AdapterType := atSLIP;
end;
71:
begin
AdapterType := atWLAN;
end;
else
begin
AdapterType := atUnknown;
end;
end;
IPAddress := String(Ptr^.IpAddressList.IpAddress.S);
NetMask := String(Ptr^.IpAddressList.IpMask.S);
Gateway := String(Ptr^.GatewayList.IpAddress.S);
if Ptr^.DhcpEnabled = 0 then
begin
DHCPServer := '';
end
else
begin
DHCPServer := String(Ptr^.DhcpServer.IpAddress.S);
end;
if Assigned(Func) then
begin
if Func(AdapterName,Description,HardwareAddress,AdapterIndex,
AdapterType,Ptr^.DhcpEnabled <> 0,IPAddress,NetMask,
Gateway,DHCPServer,Data) = False then
begin
Break;
end;
end;
Ptr := Ptr^.Next;
end;
finally
FreeMem(pAdapterInfo);
end;
end;
とします。Delphi 2009以降の無名メソッド(anonymous method)を使用する場合はこんな感じに。type
TAdapterType = (atUnknown,
atOther,
atEthernet,
atTokenRing,
atFDDI,
atPPP,
atLoopback,
atSLIP,
atWLAN);
TEnumAdapterInfoFunc = reference to
function (const AdapterName: String;
const Description: String;
const HardwareAddress: String;
AdapterIndex: Integer;
AdapterType: TAdapterType;
DhcpEnabled: Boolean;
const IPAddress: String;
const Mask: String;
const Gateway: String;
const DHCPServer: String): Boolean;
procedure EnumAdapterInfo(Func: TEnumAdapterInfoFunc);
function FormatHardwareAddress(Ptr: PIP_ADAPTER_INFO): String;
var
Index: Integer;
begin
Result := '';
for Index := 0 to Ptr^.AddressLength - 1 do
begin
Result := Result + Format('%02.2X-',[Ptr^.Address[Index]]);
end;
if Result <> '' then
begin
Delete(Result,Length(Result),1);
end;
end;
var
pAdapterInfo: PIP_ADAPTER_INFO;
Ptr: PIP_ADAPTER_INFO;
pOutBufLen: ULONG;
RetVal: DWORD;
AdapterIndex: Integer;
AdapterName: String;
Description: String;
HardwareAddress: String;
AdapterType: TAdapterType;
IPAddress: String;
NetMask: String;
Gateway: String;
DHCPServer: String;
begin
pOutBufLen := SizeOf(IP_ADAPTER_INFO);
pAdapterInfo := AllocMem(pOutBufLen);
try
RetVal := GetAdaptersInfo(pAdapterInfo,pOutBufLen);
if RetVal = ERROR_BUFFER_OVERFLOW then
begin
FreeMem(pAdapterInfo);
pAdapterInfo := AllocMem(pOutBufLen);
RetVal := GetAdaptersInfo(pAdapterInfo,pOutBufLen);
end;
if RetVal <> NO_ERROR then
begin
Exit;
end;
Ptr := pAdapterInfo;
while Ptr <> nil do
begin
AdapterName := Trim(String(Ptr^.AdapterName));
Description := Trim(String(Ptr^.Description));
HardwareAddress := FormatHardwareAddress(Ptr);
AdapterIndex := Ptr^.Index;
case Ptr^.Type_ of
MIB_IF_TYPE_OTHER:
begin
AdapterType := atOther;
end;
MIB_IF_TYPE_ETHERNET:
begin
AdapterType := atEthernet;
end;
MIB_IF_TYPE_TOKENRING:
begin
AdapterType := atTokenRing;
end;
MIB_IF_TYPE_FDDI:
begin
AdapterType := atFDDI;
end;
MIB_IF_TYPE_PPP:
begin
AdapterType := atPPP;
end;
MIB_IF_TYPE_LOOPBACK:
begin
AdapterType := atLoopback;
end;
MIB_IF_TYPE_SLIP:
begin
AdapterType := atSLIP;
end;
71:
begin
AdapterType := atWLAN;
end;
else
begin
AdapterType := atUnknown;
end;
end;
IPAddress := String(Ptr^.IpAddressList.IpAddress.S);
NetMask := String(Ptr^.IpAddressList.IpMask.S);
Gateway := String(Ptr^.GatewayList.IpAddress.S);
if Ptr^.DhcpEnabled = 0 then
begin
DHCPServer := '';
end
else
begin
DHCPServer := String(Ptr^.DhcpServer.IpAddress.S);
end;
if Assigned(Func) then
begin
if Func(AdapterName,Description,HardwareAddress,AdapterIndex,
AdapterType,Ptr^.DhcpEnabled <> 0,IPAddress,NetMask,
Gateway,DHCPServer) = False then
begin
Break;
end;
end;
Ptr := Ptr^.Next;
end;
finally
FreeMem(pAdapterInfo);
end;
end;
なおIP_ADAPTER_INFO構造体のTypeの値として無線LANの場合の定義がMIB_IF_TYPE_...にはありませんが、実際には71が格納されるようです。またIPv6(Windows XP以降)の場合はGetAdaptersAddressesを使用する必要があります。