Получить информацию об установленных сетевых адаптерах

Я использую Delphi XE2 Update 4 в Windows XP sp3

Я ищу, чтобы получить максимально возможную информацию от установленных сетевых адаптеров, особенно широковещательных IP.

Для этого я использовал этот код от Яна Шульца, который я получилиз этой статьи.

Единица измерения:

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.

Пример вызова:

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;

Код, по-видимому, работает, однако он возвращает только один сетевой интерфейс, loopback (127.0.0.0), и он также должен возвращать мой сетевой интерфейс.

В этой части кода всегда возвращается только один доступный интерфейс:

NoOfInterfaces: = NoOfBytesReturned Div SizeOf (Interface_Info);

Для работы на XE2 мне пришлось изменить используемую строку (AnsiString).

Я также попытался использовать модуль Winsock2, а также попытался использовать IdWinSock2 и вызовы API оттуда.

Во всех случаях API работали и возвращали только петлевой интерфейс.

Используя другую утилиту, написанную на Delphi, я мог получить этот список и локальный IP 192.168.0.112, но этот исходный код не прост в использовании.

Мой вопрос: что не так?

Ответы на вопрос(5)

Ваш ответ на вопрос