Конференция "Сети" » GetIFTable2 - помогите разобраться.
 
  • tytus (03.02.10 12:11) [0]
    Добрый день мастера.
    С функцией
    GetIFTable (MIB_IF_ROW)

    проблем нет.
    Вот как я объявил соотв. типы:
    NET_LUID = record
       case Integer of
         0: (Value: DWORD); //UInt64 --> DWORD
         1: (Reserved: DWORD; NetLuidIndex: DWORD; IfType: DWORD);
      end;



    NET_IFINDEX = ULONG;



    PMIB_IF_ROW2 = ^MIB_IF_ROW2;
     MIB_IF_ROW2 = packed record
       InterfaceLuid: NET_LUID;
       InterfaceIndex: NET_IFINDEX;
       InterfaceGuid: TGUID;
       Alias: array[0..IF_MAX_STRING_SIZE - 1] of WideChar;
       Description: array[0..IF_MAX_STRING_SIZE - 1]of WideChar;
       PhysicalAddressLength: ULONG
       PhysicalAddress: array[0..IF_MAX_PHYS_ADDRESS_LENGTH - 1] of Byte;
       PermanentPhysicalAddress: array[0..IF_MAX_PHYS_ADDRESS_LENGTH- 1]of Byte;
       Mtu: Cardinal;
       aType: Cardinal;//IFTYPE;
       TunnelType: TUNNEL_TYPE;
       MediaType: NDIS_MEDIUM;
       PhysicalMediumType: NDIS_PHYSICAL_MEDIUM;
       AccessType: NET_IF_ACCESS_TYPE;
       DirectionType: NET_IF_DIRECTION_TYPE;
       InterfaceAndOperStatusFlags: TInterfaceAndOperStatusFlags;
       OperStatus: IF_OPER_STATUS;
       AdminStatus: NET_IF_ADMIN_STATUS;
       MediaConnectState: NET_IF_MEDIA_CONNECT_STATE;
       NetworkGuid: TGUID;//NET_IF_NETWORK_GUID;
       ConnectionType: NET_IF_CONNECTION_TYPE;
       TransmitLinkSpeed: DWORD;//UInt64
       ReceiveLinkSpeed: DWORD;
       InOctets: DWORD;
       InUcastPkts: DWORD;
       InNUcastPkts: DWORD;
       InDiscards: DWORD;
       InErrors: DWORD;
       InUnknownProtos: DWORD;
       InUcastOctets: DWORD;
       InMulticastOctets: DWORD;
       InBroadcastOctets: DWORD;
       OutOctets: DWORD;
       OutUcastPkts: DWORD;
       OutNUcastPkts: DWORD;
       OutDiscards: DWORD;
       OutErrors: DWORD;
       OutUcastOctets: DWORD;
       OutMulticastOctets: DWORD;
       OutBroadcastOctets: DWORD;
       OutQLen: DWORD;
     end;



    PMIB_IF_TABLE2 = ^MIB_IF_TABLE2;
     MIB_IF_TABLE2 = packed record
       NumEntries: DWORD;
       Table: array[0..ANY_SIZE - 1] of MIB_IF_ROW2;
     end;



    var  IfTable2: PMIB_IF_TABLE2;
     res: integer;
     hHeap: Cardinal;
    begin
     hHeap := GetProcessHeap;
     IFTable2 := HeapAlloc(hHeap, HEAP_ZERO_MEMORY, buf_size);
     res := GetIFTable2(IFTable2);


    Каждый раз возвращаются другие значения IfTablwe2^.NumEntries , и всегда нереальные : 360125, 178552 и т.п.
    Подскажите, как с этим бороться.))
  • tytus (05.02.10 12:46) [1]
    ... разобрался с вызовом GetIfTable2.
    Возвращает правильное кол-во интерфейсов.
    Теперь вопрос в следующем.
    Как читать записи?

    for i := 0 to IFTable2^.NumEntries - 1 do
    begin
      Log(IfTable2^.Table[i].Description);
    end;



    Так вот - или пустая строка, или неверное имя, к примеру
    "iniport IP(v6)"
    В доке сказано:

    > Note that the returned MIB_IF_TABLE2 structure pointed to
    > by the Table parameter may contain padding for alignment
    > between the NumEntries member and the first MIB_IF_ROW2
    > array entry in the Table member of the MIB_IF_TABLE2 structure.
    >  

    Какя понял - речь идет о смещении для выравнивания между значением NumEntries и первым элементом массива MIB_IF_TABLE2.
    Что за смещение и чему оно равно ???
  • Vladimir komissarov (12.02.10 14:34) [2]
    Здравствуйте, я сейчас столкнулся с проблемой getiftable и w7
    и случайно попал сюда. Не могли бы Вы просветить как использовать getiftable2 для подсчета трафика? Заранее благодарен
  • Vladimir komissarov (16.02.10 11:23) [3]
    tytus - здрвствуйте, у меня тоже NumEntries  не работает, может я наступаю на те же грабли что и ты?

    var
    GetIfTable2:function(pIfTable2 : PMIB_IF_TABLE2): DWORD; stdcall;

    // функция возвращает имя интерфейса по номеру

    function tmrGetAdapters2(var InterfaceName: string; AdapterIndex : DWORD) : boolean;

    implementation

    function tmrGetAdapters2(var InterfaceName: string; AdapterIndex : DWORD) : boolean;

    var
     FLibHandle : THandle;
     Table2: MIB_IF_TABLE2;
    begin
     Result := false;
     FLibHandle := LoadLibrary('IPHLPAPI.DLL');
     if FLibHandle = 0 then Exit;
     @GetIfTable2 := GetProcAddress(FLibHandle, 'GetIfTable2');
     if not Assigned(GetIfTable2) then
     begin
       FreeLibrary(FLibHandle);
       Exit;
     end;

     if (GetIfTable2(@Table2) = 0) and
       (AdapterIndex <= @Table2.NumEntries-1) then
       begin
          InterfaceName := String(@Table2.Table[AdapterIndex].Description);
          Result := true
       end
         else Result := false;
     FreeLibrary(FLibHandle);
    end;

    procedure TFormMain.ComboBox1Enter(Sender: TObject);
    var i : integer;
       IntName : string;
    begin
     with ComboBox1 do
     begin
      Items.Clear;
      i := 0;
      while tmrGetAdapters2(IntName, i) do
      begin
        Items.Add(IntName);
        Inc(i);
      end
     end
    end;
  • tytus (22.02.10 16:57) [4]
    >Vladimir komissarov  
    Вся проблема с вызовом GetIfTable2 заключалась в неправильном описании MIB_IF_TABLE2. Вот правильное описание:
    PMIB_IF_ROW2 = ^MIB_IF_ROW2;
     _MIB_IF_ROW2 = packed record
       InterfaceLuid: NET_LUID;
       InterfaceIndex: NET_IFINDEX;
       InterfaceGuid: TGUID;
       Alias: array[0..IF_MAX_STRING_SIZE] of WideChar;
       Description: array[0..IF_MAX_STRING_SIZE] of WideChar;
       PhysicalAddressLength: Cardinal;
       PhysicalAddress: array[0..IF_MAX_PHYS_ADDRESS_LENGTH - 1] of Byte;
       PermanentPhysicalAddress: array[0..IF_MAX_PHYS_ADDRESS_LENGTH - 1]of Byte;
       Mtu: Cardinal;//ULONG;
       aType: Cardinal;
       TunnelType: Cardinal;
       MediaType: Cardinal;
       PhysicalMediumType: Cardinal;
       AccessType: Cardinal;
       DirectionType: Cardinal;
       InterfaceAndOperStatusFlags: Cardinal;// 8 значений, поразрядное ИЛИ TInterfaceAndOperStatusFlags;
       OperStatus: Cardinal;
       AdminStatus: Cardinal;
       MediaConnectState: Cardinal;
       NetworkGuid: TGUID;
       ConnectionType: Cardinal;
       TransmitLinkSpeed: UInt64;
       ReceiveLinkSpeed: UInt64;
       InOctets: UInt64;
       InUcastPkts: UInt64;
       InNUcastPkts: UInt64;
       InDiscards: UInt64;
       InErrors: UInt64;
       InUnknownProtos: UInt64;
       InUcastOctets: UInt64;
       InMulticastOctets: UInt64;
       InBroadcastOctets: UInt64;
       OutOctets: UInt64;
       OutUcastPkts: UInt64;
       OutNUcastPkts: UInt64;
       OutDiscards: UInt64;
       OutErrors: UInt64;
       OutUcastOctets: UInt64;
       OutMulticastOctets: UInt64;
       OutBroadcastOctets: UInt64;
       OutQLen: UInt64;
     end;
     MIB_IF_ROW2 = _MIB_IF_ROW2;
     TMibIfRow2 = MIB_IF_ROW2;
     PMibIfRow2 = PMIB_IF_ROW2;

     TMibIfArray2 = array [0..ANY_SIZE - 1] of TMibIfRow2;
     PMibIfArray2 = ^TMibIfArray2;

     PMIB_IF_TABLE2 = ^MIB_IF_TABLE2;
     _MIB_IF_TABLE2 = packed record
       NumEntries: Cardinal;
       Table: array[0..ANY_SIZE - 1] of _MIB_IF_ROW2;
     end;
     MIB_IF_TABLE2 = _MIB_IF_TABLE2;
     TMibIfTable2 = MIB_IF_TABLE2;
     PMibIfTable2 = PMIB_IF_TABLE2;


    Збило меня с толку описание InterfaceAndOperStatusFlags в MSDN-е описано как структура из 8-ми элементов типа boolean. Вот я и думал - что это запись, а оказалось - простой Cardinal. Легко проверить и соотв. флаги - выдернуть патч-корд и посмотреть что изменилось!
    На счет - GetIfEntry2 - пока не осилил. Возвращает или 87 (параметр задан неверно) или 2 - не знаю, что за ошибка. Посему нужный адаптер можно выбрать как
    IfTable2^.Table[Нужный адаптер];


    Ну и в флаге InterfaceAndOperStatusFlags можно смотреть - аппаратный-ли интерфейс или логический.
    Пишу на Delphi 2010 под Windows7.
    Удачи. Напиши что получилось.
    Вообще-то я написал свой IpHelper.pas, кое-что стянул из джедаев, кое-что - из родного MSDN. Если что - пиши в форум.

    P.S. IF_MAX_STRING_SIZE = 256. Итого - от 0.. до ..256 = 257 Символов в UNICODE.
    IF_MAX_PHYS_ADDRESS_LENGTH = 32.
  • tytus (22.02.10 17:03) [5]
    >Vladimir komissarov  
    На счет подсчета трафика.
    Там значения в UInt64.
    Я делал так:
    function IfBytesToStr(aValue: UInt64): string;
    var
     int_value: Int64;
    begin
     int_value := Int64Rec(aValue).Hi + Int64Rec(aValue).Lo;
    if Int64(int_value) = 0 then
       Result := '0 байт'
     else
     if Int64(int_value) < 100 then
       Result := IntToStr(int_value) + ' байт'
     else
       Result := FormatFloat('0,00', int_value) + ' байт';
    end;


    Передавать нужно
    OutUcastOctets

    и
    InUcastOctets

    , тогда значения будут точно такие-же как в свойствах сетевого подключения.
    Напишите результаты.
  • Vladimir komissarov (24.02.10 15:54) [6]
    Спасибо, попробую и отпишу
  • ddrzhivago (19.03.10 17:57) [7]
    tytus

    Mozhete privesti polnii kod kak opredelit fizicheskie MAC adresa? chto-to u menia ne poluchaetsia (u menia delphi2009 i win7 tozhe)
  • tytus (31.03.10 14:20) [8]
    > ddrzhivago   (19.03.10 17:57) [7]
    MAC-адреса записаны в полях

      PhysicalAddress
    и
      PermanentPhysicalAddress
    Это массивы Unicode символов. D12 нормально должен "понять".

    PhysicalAddressLength - длина массива (кол-во символов).
    Если = 0 - то и MAC-адреса нету.

    На вскидку не помню, а проверить в данный момент времени немогу.
  • Aidar (15.01.11 07:21) [9]
    est' primery na Delphi???????????//
 
Конференция "Сети" » GetIFTable2 - помогите разобраться.
Есть новые Нет новых   [134431   +10][b:0][p:0.003]