获取有关已安装网络适配器的信息 [英] Get information about the installed network adapters
问题描述
我正在寻找从安装的网络适配器获得最大可能的信息,特别是广播ip。
为此我使用Jan Schulz的这段代码,我得到了来自本文。
单位:
单位USock;
界面
使用Windows,Winsock;
{识别网络接口的单位
此代码至少需要Win98 / ME / 2K,95 OSR 2或NT服务包#3
,因为使用WinSock 2(WS2_32 .DLL)}
//在非正式记录的手册中找到的常量M $ Winsock函数
Const SIO_GET_INTERFACE_LIST = $ 4004747F;
IFF_UP = $ 00000001;
IFF_BROADCAST = $ 00000002;
IFF_LOOPBACK = $ 00000004;
IFF_POINTTOPOINT = $ 00000008;
IFF_MULTICAST = $ 00000010;
类型SockAddr_Gen =打包记录
AddressIn:SockAddr_In;
填充:包装数组[0..7]的Char;
结束
Interface_Info =记录
iiFlags:u_Long;
ii地址:SockAddr_Gen;
iiBroadcastAddress:SockAddr_Gen;
ii网络掩码:SockAddr_Gen;
结束
tNetworkInterface =记录
ComputerName:String;
AddrIP:String;
SubnetMask:String;
AddrNet:String;
AddrLimitedBroadcast:String;
AddrDirectedBroadcast:String;
IsInterfaceUp:Boolean;
BroadcastSupport:Boolean;
IsLoopback:Boolean;
结束
tNetworkInterfaceList = tNetworkInterface的数组;
函数WSAIoctl(aSocket:TSocket;
aCommand:DWord;
lpInBuffer:PChar;
dwInBufferLen:DWord;
lpOutBuffer:PChar ;
dwOutBufferLen:DWord;
lpdwOutBytesReturned:LPDWord;
lpOverLapped:Pointer;
lpOverLappedRoutine:Pointer):Integer;标准外部WS2_32.DLL;
函数GetNetworkInterfaces(Var aNetworkInterfaceList:tNetworkInterfaceList):Boolean;
实现
函数GetNetworkInterfaces(Var aNetworkInterfaceList:tNetworkInterfaceList):Boolean;
//返回系统上可用的网络接口(IPv4)的完整列表
//版权所有:Jan Schulz博士,2007年3月23日至26日
//可以使用此版本为自由和非盈利性项目。在任何其他情况下联系
//从MSDN
// www.code10.net
获取的信息写入Var aSocket:TSocket;
aWSADataRecord:WSAData;
NoOfInterfaces:Integer;
NoOfBytesReturned:u_Long;
InterfaceFlags:u_Long;
NameLength:DWord;
pAddrIP:SockAddr_In;
pAddrSubnetMask:SockAddr_In;
pAddrBroadcast:Sockaddr_In;
pIPString:PChar;
pSubnetMaskString:PChar;
pLimBroadcastString:PChar;
pNetAddrString:PChar;
pDirBroadcastString:PChar;
DirBroadcastDummy:In_Addr;
NetAddrDummy:In_Addr;
缓冲区:Interface_Info的Array [0..30]
i:整数;
开始
结果:= False;
SetLength(aNetworkInterfaceList,0);
//启动旧的WinSock
// WSAStartup($ 0101,aWSADataRecord);
//启动WinSock2
WSAStartup(MAKEWORD(2,0),aWSADataRecord);
//打开一个套接字
aSocket:= Socket(AF_INET,SOCK_STREAM,0);
//如果不可能打开套接字,不值得再去
如果(aSocket = INVALID_SOCKET)则退出;
尝试
如果WSAIoCtl(aSocket,SIO_GET_INTERFACE_LIST,NIL,0,
@Buffer,1024,@NoOfBytesReturned,NIL,NIL) SOCKET_ERROR THEN
开始
NoOfInterfaces:= NoOfBytesReturned Div SizeOf(Interface_Info);
SetLength(aNetworkInterfaceList,NoOfInterfaces);
//对于每个标识的接口,get:
对于i:= 0到NoOfInterfaces - 1 do
开始
使用aNetworkInterfaceList [i] do
开始
//获取机器的名称
NameLength:= MAX_COMPUTERNAME_LENGTH + 1;
SetLength(ComputerName,NameLength);
如果不是Windows.GetComputerName(PChar(Computername),NameLength)THen ComputerName:='';
//获取IP地址
pAddrIP:=缓冲区[i] .iiAddress.AddressIn;
pIPString:= inet_ntoa(pAddrIP.Sin_Addr);
AddrIP:= pIPString;
//获取子网掩码
pAddrSubnetMask:= Buffer [i] .iiNetMask.AddressIn;
pSubnetMaskString:= inet_ntoa(pAddrSubnetMask.Sin_Addr);
SubnetMask:= pSubnetMaskString;
//获取有限的广播地址
pAddrBroadcast:= Buffer [i] .iiBroadCastAddress.AddressIn;
pLimBroadcastString:= inet_ntoa(pAddrBroadcast.Sin_Addr);
AddrLimitedBroadcast:= pLimBroadcastString;
//计算网络和定向广播地址
NetAddrDummy.S_addr:= Buffer [i] .iiAddress.AddressIn.Sin_Addr.S_Addr;
NetAddrDummy.S_addr:= NetAddrDummy.S_addr And Buffer [i] .iiNetMask.AddressIn.Sin_Addr.S_Addr;
DirBroadcastDummy.S_addr:= NetAddrDummy.S_addr或Not Buffer [i] .iiNetMask.AddressIn.Sin_Addr.S_Addr;
pNetAddrString:= inet_ntoa((NetAddrDummy));
AddrNet:= pNetAddrString;
pDirBroadcastString:= inet_ntoa((DirBroadcastDummy));
AddrDirectedBroadcast:= pDirBroadcastString;
//从标记的评估我们收到更多信息
InterfaceFlags:= Buffer [i] .iiFlags;
//网络接口是up还是down?
如果(InterfaceFlags和IFF_UP)= IFF_UP,那么IsInterfaceUp:= True
否则IsInterfaceUp:= False;
//网络接口是否支持有限广播?
If(InterfaceFlags和IFF_BROADCAST)= IFF_BROADCAST THEN BroadcastSupport:= True
Else BroadcastSupport:= False;
//网络接口是否是环回接口?
如果(InterfaceFlags和IFF_LOOPBACK)= IFF_LOOPBACK,那么IsLoopback:= True
Else IsLoopback:= False;
结束
结束
结束
除了
结果:= False;
结束
//清理乱码
CloseSocket(aSocket);
WSACleanUp;
结果:= True;
结束
结束。
示例调用:
使用USock;
过程TForm1.Button1Click(Sender:TObject);
Var i:整数;
aNetInterfaceList:tNetworkInterfaceList;
开始
如果(GetNetworkInterfaces(aNetInterfaceList))THen
开始
Memo1.Clear;
Memo1.Lines.Add(DateTimeToStr(Now)+':');
对于i:= 0到高(aNetInterfaceList)do
开始
Memo1.Lines.Add('');
Memo1.Lines.Add('#:'+ IntToStr(i));
Memo1.Lines.Add('Name:'+ aNetInterfaceList [i] .ComputerName);
Memo1.Lines.Add('IP-Address:'+ aNetInterfaceList [i] .AddrIP);
Memo1.Lines.Add('Subnet mask:'+ aNetInterfaceList [i] .SubnetMask);
Memo1.Lines.Add('net address:'+ aNetInterfaceList [i] .AddrNet);
Memo1.Lines.Add('有限广播地址:'+ aNetInterfaceList [i] .AddrLimitedBroadcast);
Memo1.Lines.Add('Directed Broadcast address:'+ aNetInterfaceList [i] .AddrDirectedBroadcast);
Memo1.Lines.Add('Interface up:'+ BoolToStr(aNetInterfaceList [i] .IsInterfaceUp,True));
Memo1.Lines.Add('Broadcast supported:'+ BoolToStr(aNetInterfaceList [i] .BroadcastSupport,True));
Memo1.Lines.Add('Loopback interface:'+ BoolToStr(aNetInterfaceList [i] .IsLoopback,True));
Memo1.Lines.Add('');
结束
结束
结束
代码显然有效,但只返回一个网络接口,环回(127.0.0.0)它也应该返回我的网络私有界面。
在这部分代码中,它总是返回一个可用的界面:
NoOfInterfaces:= NoOfBytesReturned Div SizeOf(Interface_Info);
要在XE2上工作,我不得不更改使用的字符串(AnsiString)。
我也尝试使用Winsock2单元,并尝试使用IdWinSock2和API调用。
在所有情况下,API都工作并返回只有回送接口。
使用在delphi上编写的其他实用程序,我可以得到一个这个列表,本地IP 192.168.0.112被列出,但是这个源代码是
我的问题是:有什么问题?
Jan Schulz的代码在正确转换为uni时正常工作代码友好的Delphi。
我做了一些更正:
-
由于 TOndrej 已经指出,
char
必须转换为AnsiChar
需要时。在这种情况下,这只会发生在SockAddr_Gen
记录的Padding
字段中,这不仅是修复了记录,而且还导致SizeOf(Interface_Info)
,然后NoOfInterfaces
返回错误的结果。因为它不是一个字符,最好将它定义为字节
。 -
掉落
PChars
用于保存inet_ntoa
调用的结果,并分配TNetworkInterface
字符串字段直接。 -
中的字符串
TNetworkInterfaceComputerName
被传递给GetComputerName
api,它期望一个PWideChar
/PChar
。
单位USock;
界面
使用Windows,Winsock;
{识别网络接口的单位
此代码至少需要Win98 / ME / 2K,95 OSR 2或NT服务包#3
作为WinSock 2使用(WS2_32.DLL)}
//在非正式记录的M $ Winsock函数中找到的常量
Const SIO_GET_INTERFACE_LIST = $ 4004747F;
IFF_UP = $ 00000001;
IFF_BROADCAST = $ 00000002;
IFF_LOOPBACK = $ 00000004;
IFF_POINTTOPOINT = $ 00000008;
IFF_MULTICAST = $ 00000010;
类型SockAddr_Gen =打包记录
AddressIn:SockAddr_In;
填充:Byte的Packed Array [0..7];
结束
Interface_Info =记录
iiFlags:u_Long;
ii地址:SockAddr_Gen;
iiBroadcastAddress:SockAddr_Gen;
ii网络掩码:SockAddr_Gen;
结束
tNetworkInterface =记录
ComputerName:String;
AddrIP:String;
SubnetMask:String;
AddrNet:String;
AddrLimitedBroadcast:String;
AddrDirectedBroadcast:String;
IsInterfaceUp:Boolean;
BroadcastSupport:Boolean;
IsLoopback:Boolean;
结束
tNetworkInterfaceList = tNetworkInterface的数组;
函数WSAIoctl(aSocket:TSocket;
aCommand:DWord;
lpInBuffer:Pointer;
dwInBufferLen:DWord;
lpOutBuffer:Pointer ;
dwOutBufferLen:DWord;
lpdwOutBytesReturned:LPDWord;
lpOverLapped:Pointer;
lpOverLappedRoutine:Pointer):Integer;标准外部WS2_32.DLL;
函数GetNetworkInterfaces(Var aNetworkInterfaceList:tNetworkInterfaceList):Boolean;
实现
函数GetNetworkInterfaces(Var aNetworkInterfaceList:tNetworkInterfaceList):Boolean;
//返回系统上可用的网络接口(IPv4)的完整列表
//版权所有:Jan Schulz博士,2007年3月23日至26日
//可以使用此版本为自由和非盈利性项目。在任何其他情况下联系
//从MSDN
// www.code10.net
获取的信息写入Var aSocket:TSocket;
aWSADataRecord:WSAData;
NoOfInterfaces:Integer;
NoOfBytesReturned:u_Long;
InterfaceFlags:u_Long;
NameLength:DWord;
pAddrIP:SockAddr_In;
pAddrSubnetMask:SockAddr_In;
pAddrBroadcast:Sockaddr_In;
DirBroadcastDummy:In_Addr;
NetAddrDummy:In_Addr;
缓冲区:Interface_Info的Array [0..30]
i:整数;
开始
结果:= False;
SetLength(aNetworkInterfaceList,0);
//启动旧的WinSock
// WSAStartup($ 0101,aWSADataRecord);
//启动WinSock2
WSAStartup(MAKEWORD(2,0),aWSADataRecord);
//打开一个套接字
aSocket:= Socket(AF_INET,SOCK_STREAM,0);
//如果不可能打开套接字,不值得再去
如果(aSocket = INVALID_SOCKET)则退出;
尝试
如果WSAIoCtl(aSocket,SIO_GET_INTERFACE_LIST,NIL,0,
@Buffer,1024,@NoOfBytesReturned,NIL,NIL) SOCKET_ERROR THEN
开始
NoOfInterfaces:= NoOfBytesReturned Div SizeOf(Interface_Info);
SetLength(aNetworkInterfaceList,NoOfInterfaces);
//对于每个标识的接口,get:
对于i:= 0到NoOfInterfaces - 1 do
开始
使用aNetworkInterfaceList [i] do
开始
//获取机器的名称
NameLength:= MAX_COMPUTERNAME_LENGTH + 1;
SetLength(ComputerName,NameLength);
如果不是GetComputerName(PChar(Computername),NameLength)THen ComputerName:='';
//获取IP地址
pAddrIP:=缓冲区[i] .iiAddress.AddressIn;
AddrIP:= string(inet_ntoa(pAddrIP.Sin_Addr));
//获取子网掩码
pAddrSubnetMask:= Buffer [i] .iiNetMask.AddressIn;
SubnetMask:= string(inet_ntoa(pAddrSubnetMask.Sin_Addr));
//获取有限的广播地址
pAddrBroadcast:= Buffer [i] .iiBroadCastAddress.AddressIn;
AddrLimitedBroadcast:= string(inet_ntoa(pAddrBroadcast.Sin_Addr));
//计算网络和定向广播地址
NetAddrDummy.S_addr:= Buffer [i] .iiAddress.AddressIn.Sin_Addr.S_Addr;
NetAddrDummy.S_addr:= NetAddrDummy.S_addr And Buffer [i] .iiNetMask.AddressIn.Sin_Addr.S_Addr;
DirBroadcastDummy.S_addr:= NetAddrDummy.S_addr或Not Buffer [i] .iiNetMask.AddressIn.Sin_Addr.S_Addr;
AddrNet:= string(inet_ntoa((NetAddrDummy)));
AddrDirectedBroadcast:= string(inet_ntoa((DirBroadcastDummy)));
//从标记的评估我们收到更多信息
InterfaceFlags:= Buffer [i] .iiFlags;
//网络接口是up还是down?
如果(InterfaceFlags和IFF_UP)= IFF_UP,那么IsInterfaceUp:= True
否则IsInterfaceUp:= False;
//网络接口是否支持有限广播?
If(InterfaceFlags和IFF_BROADCAST)= IFF_BROADCAST THEN BroadcastSupport:= True
Else BroadcastSupport:= False;
//网络接口是否是环回接口?
如果(InterfaceFlags和IFF_LOOPBACK)= IFF_LOOPBACK,那么IsLoopback:= True
Else IsLoopback:= False;
结束
结束
结束
除
//结果:= False;
结束
//清理乱码
CloseSocket(aSocket);
WSACleanUp;
结果:= True;
结束
结束。
I am using Delphi XE2 Update 4 on Windows XP sp3
I am looking to get max possible information from installed network adapters, specially the broadcast ip.
For that I used this code from Jan Schulz that I got from this article.
Unit:
Unit USock;
Interface
Uses Windows, Winsock;
{ Unit to identify the network interfaces
This code requires at least Win98/ME/2K, 95 OSR 2 or NT service pack #3
as WinSock 2 is used (WS2_32.DLL) }
// Constants found in manual on non-officially documented M$ Winsock functions
Const SIO_GET_INTERFACE_LIST = $4004747F;
IFF_UP = $00000001;
IFF_BROADCAST = $00000002;
IFF_LOOPBACK = $00000004;
IFF_POINTTOPOINT = $00000008;
IFF_MULTICAST = $00000010;
Type SockAddr_Gen = Packed Record
AddressIn : SockAddr_In;
Padding : Packed Array [0..7] of Char;
end;
Interface_Info = Record
iiFlags : u_Long;
iiAddress : SockAddr_Gen;
iiBroadcastAddress : SockAddr_Gen;
iiNetmask : SockAddr_Gen;
end;
tNetworkInterface = Record
ComputerName : String;
AddrIP : String;
SubnetMask : String;
AddrNet : String;
AddrLimitedBroadcast : String;
AddrDirectedBroadcast : String;
IsInterfaceUp : Boolean;
BroadcastSupport : Boolean;
IsLoopback : Boolean;
end;
tNetworkInterfaceList = Array of tNetworkInterface;
Function WSAIoctl (aSocket : TSocket;
aCommand : DWord;
lpInBuffer : PChar;
dwInBufferLen : DWord;
lpOutBuffer : PChar;
dwOutBufferLen : DWord;
lpdwOutBytesReturned : LPDWord;
lpOverLapped : Pointer;
lpOverLappedRoutine : Pointer) : Integer; stdcall; external 'WS2_32.DLL';
Function GetNetworkInterfaces (Var aNetworkInterfaceList : tNetworkInterfaceList): Boolean;
Implementation
Function GetNetworkInterfaces (Var aNetworkInterfaceList : tNetworkInterfaceList): Boolean;
// Returns a complete list the of available network interfaces on a system (IPv4)
// Copyright by Dr. Jan Schulz, 23-26th March 2007
// This version can be used for free and non-profit projects. In any other case get in contact
// Written with information retrieved from MSDN
// www.code10.net
Var aSocket : TSocket;
aWSADataRecord : WSAData;
NoOfInterfaces : Integer;
NoOfBytesReturned : u_Long;
InterfaceFlags : u_Long;
NameLength : DWord;
pAddrIP : SockAddr_In;
pAddrSubnetMask : SockAddr_In;
pAddrBroadcast : Sockaddr_In;
pIPString : PChar;
pSubnetMaskString : PChar;
pLimBroadcastString : PChar;
pNetAddrString : PChar;
pDirBroadcastString : PChar;
DirBroadcastDummy : In_Addr;
NetAddrDummy : In_Addr;
Buffer : Array [0..30] of Interface_Info;
i : Integer;
Begin
Result := False;
SetLength (aNetworkInterfaceList, 0);
// Startup of old the WinSock
// WSAStartup ($0101, aWSADataRecord);
// Startup of WinSock2
WSAStartup(MAKEWORD(2, 0), aWSADataRecord);
// Open a socket
aSocket := Socket (AF_INET, SOCK_STREAM, 0);
// If impossible to open a socket, not worthy to go any further
If (aSocket = INVALID_SOCKET) THen Exit;
Try
If WSAIoCtl (aSocket, SIO_GET_INTERFACE_LIST, NIL, 0,
@Buffer, 1024, @NoOfBytesReturned, NIL, NIL) <> SOCKET_ERROR THen
Begin
NoOfInterfaces := NoOfBytesReturned Div SizeOf (Interface_Info);
SetLength (aNetworkInterfaceList, NoOfInterfaces);
// For each of the identified interfaces get:
For i := 0 to NoOfInterfaces - 1 do
Begin
With aNetworkInterfaceList[i] do
Begin
// Get the name of the machine
NameLength := MAX_COMPUTERNAME_LENGTH + 1;
SetLength (ComputerName, NameLength) ;
If Not Windows.GetComputerName (PChar (Computername), NameLength) THen ComputerName := '';
// Get the IP address
pAddrIP := Buffer[i].iiAddress.AddressIn;
pIPString := inet_ntoa (pAddrIP.Sin_Addr);
AddrIP := pIPString;
// Get the subnet mask
pAddrSubnetMask := Buffer[i].iiNetMask.AddressIn;
pSubnetMaskString := inet_ntoa (pAddrSubnetMask.Sin_Addr);
SubnetMask := pSubnetMaskString;
// Get the limited broadcast address
pAddrBroadcast := Buffer[i].iiBroadCastAddress.AddressIn;
pLimBroadcastString := inet_ntoa (pAddrBroadcast.Sin_Addr);
AddrLimitedBroadcast := pLimBroadcastString;
// Calculate the net and the directed broadcast address
NetAddrDummy.S_addr := Buffer[i].iiAddress.AddressIn.Sin_Addr.S_Addr;
NetAddrDummy.S_addr := NetAddrDummy.S_addr And Buffer[i].iiNetMask.AddressIn.Sin_Addr.S_Addr;
DirBroadcastDummy.S_addr := NetAddrDummy.S_addr Or Not Buffer[i].iiNetMask.AddressIn.Sin_Addr.S_Addr;
pNetAddrString := inet_ntoa ((NetAddrDummy));
AddrNet := pNetAddrString;
pDirBroadcastString := inet_ntoa ((DirBroadcastDummy));
AddrDirectedBroadcast := pDirBroadcastString;
// From the evaluation of the Flags we receive more information
InterfaceFlags := Buffer[i].iiFlags;
// Is the network interface up or down ?
If (InterfaceFlags And IFF_UP) = IFF_UP THen IsInterfaceUp := True
Else IsInterfaceUp := False;
// Does the network interface support limited broadcasts ?
If (InterfaceFlags And IFF_BROADCAST) = IFF_BROADCAST THen BroadcastSupport := True
Else BroadcastSupport := False;
// Is the network interface a loopback interface ?
If (InterfaceFlags And IFF_LOOPBACK) = IFF_LOOPBACK THen IsLoopback := True
Else IsLoopback := False;
end;
end;
end;
Except
Result := False;
end;
// Cleanup the mess
CloseSocket (aSocket);
WSACleanUp;
Result := True;
end;
end.
Example call:
uses USock;
Procedure TForm1.Button1Click(Sender: TObject);
Var i : Integer;
aNetInterfaceList : tNetworkInterfaceList;
Begin
If (GetNetworkInterfaces (aNetInterfaceList)) THen
Begin
Memo1.Clear;
Memo1.Lines.Add (DateTimeToStr (Now)+ ' : ');
For i := 0 to High (aNetInterfaceList) do
Begin
Memo1.Lines.Add ('');
Memo1.Lines.Add ('# : ' + IntToStr(i));
Memo1.Lines.Add ('Name : ' + aNetInterfaceList[i].ComputerName);
Memo1.Lines.Add ('IP-Address : ' + aNetInterfaceList[i].AddrIP);
Memo1.Lines.Add ('Subnet mask : ' + aNetInterfaceList[i].SubnetMask);
Memo1.Lines.Add ('Net address : ' + aNetInterfaceList[i].AddrNet);
Memo1.Lines.Add ('Limited broadcast address : ' + aNetInterfaceList[i].AddrLimitedBroadcast);
Memo1.Lines.Add ('Directed Broadcast address : ' + aNetInterfaceList[i].AddrDirectedBroadcast);
Memo1.Lines.Add ('Interface up : ' + BoolToStr (aNetInterfaceList[i].IsInterfaceUp, True));
Memo1.Lines.Add ('Broadcast supported : ' + BoolToStr (aNetInterfaceList[i].BroadcastSupport, True));
Memo1.Lines.Add ('Loopback interface : ' + BoolToStr (aNetInterfaceList[i].IsLoopback, True));
Memo1.Lines.Add ('');
end;
end;
end;
The code apparently works, however it only return one network interface, the loopback (127.0.0.0), and it should return my network private interface also.
On this part of the code it always return only one interface available:
NoOfInterfaces := NoOfBytesReturned Div SizeOf (Interface_Info);
To work on XE2 I had to change the string used (AnsiString).
I have also tried using Winsock2 unit, and also tried using IdWinSock2 and the API calls from there.
On all cases the APIs worked and returned only the loopback interface.
Using another utility written on delphi I could get a this list, and the local IP 192.168.0.112 got listed, however this source code is not easy to use.
My question is: what is wrong?
Jan Schulz's code works fine when properly converted to unicode-friendly Delphi.
I've done some corrections:
As TOndrej has pointed,
char
must be converted toAnsiChar
when needed. In this case, this only occurs in thePadding
field of theSockAddr_Gen
record, which was not only screwing the record, but also causingSizeOf(Interface_Info)
, and subsequentlyNoOfInterfaces
, to return a wrong result. Since it's not really a character, it is better to define it as abyte
.Dropped
PChars
used to hold results ofinet_ntoa
calls, and assigningTNetworkInterface
string fields directly.Strings
inTNetworkInterface
are fine, because they are not passed to any api calls. Also,ComputerName
is passed toGetComputerName
api, which expects aPWideChar
/PChar
.
Unit USock;
Interface
Uses Windows, Winsock;
{ Unit to identify the network interfaces
This code requires at least Win98/ME/2K, 95 OSR 2 or NT service pack #3
as WinSock 2 is used (WS2_32.DLL) }
// Constants found in manual on non-officially documented M$ Winsock functions
Const SIO_GET_INTERFACE_LIST = $4004747F;
IFF_UP = $00000001;
IFF_BROADCAST = $00000002;
IFF_LOOPBACK = $00000004;
IFF_POINTTOPOINT = $00000008;
IFF_MULTICAST = $00000010;
Type SockAddr_Gen = Packed Record
AddressIn : SockAddr_In;
Padding : Packed Array [0..7] of Byte;
end;
Interface_Info = Record
iiFlags : u_Long;
iiAddress : SockAddr_Gen;
iiBroadcastAddress : SockAddr_Gen;
iiNetmask : SockAddr_Gen;
end;
tNetworkInterface = Record
ComputerName : String;
AddrIP : String;
SubnetMask : String;
AddrNet : String;
AddrLimitedBroadcast : String;
AddrDirectedBroadcast : String;
IsInterfaceUp : Boolean;
BroadcastSupport : Boolean;
IsLoopback : Boolean;
end;
tNetworkInterfaceList = Array of tNetworkInterface;
Function WSAIoctl (aSocket : TSocket;
aCommand : DWord;
lpInBuffer : Pointer;
dwInBufferLen : DWord;
lpOutBuffer : Pointer;
dwOutBufferLen : DWord;
lpdwOutBytesReturned : LPDWord;
lpOverLapped : Pointer;
lpOverLappedRoutine : Pointer) : Integer; stdcall; external 'WS2_32.DLL';
Function GetNetworkInterfaces (Var aNetworkInterfaceList : tNetworkInterfaceList): Boolean;
implementation
Function GetNetworkInterfaces (Var aNetworkInterfaceList : tNetworkInterfaceList): Boolean;
// Returns a complete list the of available network interfaces on a system (IPv4)
// Copyright by Dr. Jan Schulz, 23-26th March 2007
// This version can be used for free and non-profit projects. In any other case get in contact
// Written with information retrieved from MSDN
// www.code10.net
Var aSocket : TSocket;
aWSADataRecord : WSAData;
NoOfInterfaces : Integer;
NoOfBytesReturned : u_Long;
InterfaceFlags : u_Long;
NameLength : DWord;
pAddrIP : SockAddr_In;
pAddrSubnetMask : SockAddr_In;
pAddrBroadcast : Sockaddr_In;
DirBroadcastDummy : In_Addr;
NetAddrDummy : In_Addr;
Buffer : Array [0..30] of Interface_Info;
i : Integer;
Begin
Result := False;
SetLength (aNetworkInterfaceList, 0);
// Startup of old the WinSock
// WSAStartup ($0101, aWSADataRecord);
// Startup of WinSock2
WSAStartup(MAKEWORD(2, 0), aWSADataRecord);
// Open a socket
aSocket := Socket (AF_INET, SOCK_STREAM, 0);
// If impossible to open a socket, not worthy to go any further
If (aSocket = INVALID_SOCKET) THen Exit;
Try
If WSAIoCtl (aSocket, SIO_GET_INTERFACE_LIST, NIL, 0,
@Buffer, 1024, @NoOfBytesReturned, NIL, NIL) <> SOCKET_ERROR THen
Begin
NoOfInterfaces := NoOfBytesReturned Div SizeOf (Interface_Info);
SetLength (aNetworkInterfaceList, NoOfInterfaces);
// For each of the identified interfaces get:
For i := 0 to NoOfInterfaces - 1 do
Begin
With aNetworkInterfaceList[i] do
Begin
// Get the name of the machine
NameLength := MAX_COMPUTERNAME_LENGTH + 1;
SetLength (ComputerName, NameLength) ;
If Not GetComputerName (PChar (Computername), NameLength) THen ComputerName := '';
// Get the IP address
pAddrIP := Buffer[i].iiAddress.AddressIn;
AddrIP := string(inet_ntoa (pAddrIP.Sin_Addr));
// Get the subnet mask
pAddrSubnetMask := Buffer[i].iiNetMask.AddressIn;
SubnetMask := string(inet_ntoa (pAddrSubnetMask.Sin_Addr));
// Get the limited broadcast address
pAddrBroadcast := Buffer[i].iiBroadCastAddress.AddressIn;
AddrLimitedBroadcast := string(inet_ntoa (pAddrBroadcast.Sin_Addr));
// Calculate the net and the directed broadcast address
NetAddrDummy.S_addr := Buffer[i].iiAddress.AddressIn.Sin_Addr.S_Addr;
NetAddrDummy.S_addr := NetAddrDummy.S_addr And Buffer[i].iiNetMask.AddressIn.Sin_Addr.S_Addr;
DirBroadcastDummy.S_addr := NetAddrDummy.S_addr Or Not Buffer[i].iiNetMask.AddressIn.Sin_Addr.S_Addr;
AddrNet := string(inet_ntoa ((NetAddrDummy)));
AddrDirectedBroadcast := string(inet_ntoa ((DirBroadcastDummy)));
// From the evaluation of the Flags we receive more information
InterfaceFlags := Buffer[i].iiFlags;
// Is the network interface up or down ?
If (InterfaceFlags And IFF_UP) = IFF_UP THen IsInterfaceUp := True
Else IsInterfaceUp := False;
// Does the network interface support limited broadcasts ?
If (InterfaceFlags And IFF_BROADCAST) = IFF_BROADCAST THen BroadcastSupport := True
Else BroadcastSupport := False;
// Is the network interface a loopback interface ?
If (InterfaceFlags And IFF_LOOPBACK) = IFF_LOOPBACK THen IsLoopback := True
Else IsLoopback := False;
end;
end;
end;
Except
//Result := False;
end;
// Cleanup the mess
CloseSocket (aSocket);
WSACleanUp;
Result := True;
end;
end.
这篇关于获取有关已安装网络适配器的信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!