获取有关已安装网络适配器的信息 [英] Get information about the installed network adapters

查看:227
本文介绍了获取有关已安装网络适配器的信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Windows XP SP3上的Delphi XE2 Update 4



我正在寻找从安装的网络适配器获得最大可能的信息,特别是广播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 字符串字段直接。


  • 中的字符串 TNetworkInterface 是好的,因为它们没有传递到任何api电话。另外, ComputerName 被传递给 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 to AnsiChar when needed. In this case, this only occurs in the Padding field of the SockAddr_Gen record, which was not only screwing the record, but also causing SizeOf(Interface_Info), and subsequently NoOfInterfaces, to return a wrong result. Since it's not really a character, it is better to define it as a byte.

  • Dropped PChars used to hold results of inet_ntoa calls, and assigning TNetworkInterface string fields directly.

  • Strings in TNetworkInterface are fine, because they are not passed to any api calls. Also, ComputerName is passed to GetComputerName api, which expects a PWideChar/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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆