Pregunta

He estado usando una tarjeta inalámbrica 3G por un tiempo y cada vez que me conecto, mi antivirus activa las actualizaciones.

Me pregunto cuál es el conjunto de funciones de la API de Win32 que puedo usar para recibir notificaciones o consultar sobre el evento de una conexión a Internet.

¿Y ya hay un conjunto de encabezados portados para Delphi?

¿Fue útil?

Solución

Trabajé en un proyecto para ejecutar el script de inicio de sesión de un usuario cada vez que conectaban nuestra red a través de VPN. Para hacer esto, escribí una unidad auxiliar que recupera la información del adaptador y la almacena en un registro simple.

Luego configuro una notificación de registro, vea aquí para saber cómo hacerlo en Delphi

La notificación del registro estaba en HKLM \ SYSTEM \ CurrentControlSet \ Services \ Tcpip \ Parameters \ Interfaces . Este evento de notificación se activa cada vez que Windows obtiene una nueva dirección IP o realiza algún tipo de cambio en la información de conexión de un adaptador. Cuando se activó este evento, llamé a la función (en el código a continuación) para recuperar información actualizada sobre el adaptador. Comparé esta nueva información con mi información previamente registrada ... lo que significa que tuve que guardar la consulta de información del adaptador anterior para saber si algo había cambiado.

De todos modos, aquí está mi unidad de ayuda:

unit uAdapterInfo;

interface

uses
  Classes,
  SysUtils;

const
  MAX_INTERFACE_NAME_LEN = $100;
  ERROR_SUCCESS   = 0;
  MAXLEN_IFDESCR  = $100;
  MAXLEN_PHYSADDR = 8;

  MIB_IF_OPER_STATUS_NON_OPERATIONAL = 0;
  MIB_IF_OPER_STATUS_UNREACHABLE = 1;
  MIB_IF_OPER_STATUS_DISCONNECTED = 2;
  MIB_IF_OPER_STATUS_CONNECTING  = 3;
  MIB_IF_OPER_STATUS_CONNECTED   = 4;
  MIB_IF_OPER_STATUS_OPERATIONAL = 5;

  MIB_IF_TYPE_OTHER    = 1;
  MIB_IF_TYPE_ETHERNET = 6;
  MIB_IF_TYPE_TOKENRING = 9;
  MIB_IF_TYPE_FDDI     = 15;
  MIB_IF_TYPE_PPP      = 23;
  MIB_IF_TYPE_LOOPBACK = 24;
  MIB_IF_TYPE_SLIP     = 28;

  MIB_IF_ADMIN_STATUS_UP      = 1;
  MIB_IF_ADMIN_STATUS_DOWN    = 2;
  MIB_IF_ADMIN_STATUS_TESTING = 3;

  _MAX_ROWS_ = 20;
  ANY_SIZE   = 1;


type
  MIB_IFROW = record
    wszName:    array[0 .. (MAX_INTERFACE_NAME_LEN * 2 - 1)] of ansichar;
    dwIndex:    longint;
    dwType:     longint;
    dwMtu:      longint;
    dwSpeed:    longint;
    dwPhysAddrLen: longint;
    bPhysAddr:  array[0 .. (MAXLEN_PHYSADDR - 1)] of byte;
    dwAdminStatus: longint;
    dwOperStatus: longint;
    dwLastChange: longint;
    dwInOctets: longint;
    dwInUcastPkts: longint;
    dwInNUcastPkts: longint;
    dwInDiscards: longint;
    dwInErrors: longint;
    dwInUnknownProtos: longint;
    dwOutOctets: longint;
    dwOutUcastPkts: longint;
    dwOutNUcastPkts: longint;
    dwOutDiscards: longint;
    dwOutErrors: longint;
    dwOutQLen:  longint;
    dwDescrLen: longint;
    bDescr:     array[0 .. (MAXLEN_IFDESCR - 1)] of ansichar;
  end;

type
  MIB_IPADDRROW = record
    dwAddr:      longint;
    dwIndex:     longint;
    dwMask:      longint;
    dwBCastAddr: longint;
    dwReasmSize: longint;
    unused1:     word;
    unused2:     word;
  end;

type
  _IfTable = record
    nRows: longint;
    ifRow: array[1.._MAX_ROWS_] of MIB_IFROW;
  end;

type
  _IpAddrTable = record
    dwNumEntries: longint;
    table: array[1..ANY_SIZE] of MIB_IPADDRROW;
  end;



function GetIfTable(pIfTable: Pointer; var pdwSize: longint; bOrder: longint): longint;
  stdcall;
function GetIpAddrTable(pIpAddrTable: Pointer; var pdwSize: longint;
  bOrder: longint): longint; stdcall;

function Get_if_type(iType: integer): string;
function Get_if_admin_status(iStatus: integer): string;
function Get_if_oper_status(iStatus: integer): string;


implementation

function GetIfTable; stdcall; external 'IPHLPAPI.DLL';
function GetIpAddrTable; stdcall; external 'IPHLPAPI.DLL';

function Get_if_type(iType: integer): string;
var
  sResult: string;
begin
  sResult := 'UNKNOWN';
  case iType of
    1: sResult   := 'Other';
    6: sResult   := 'Ethernet';
    9: sResult   := 'Tokenring';
    15: sResult  := 'FDDI';
    23: sResult  := 'PPP';
    24: sResult  := 'Local loopback';
    28: sResult  := 'SLIP';
    37: sResult  := 'ATM';
    71: sResult  := 'IEEE 802.11';
    131: sResult := 'Tunnel';
    144: sResult := 'IEEE 1394 (Firewire)';
  end;

  Result := sResult;
end;

function Get_if_admin_status(iStatus: integer): string;
var
  sResult: string;
begin
  sResult := 'UNKNOWN';

  case iStatus of
    1: sResult := 'UP';
    2: sResult := 'DOWN';
    3: sResult := 'TESTING';
  end;

  Result := sResult;
end;

function Get_if_oper_status(iStatus: integer): string;
var
  sResult: string;
begin
  sResult := 'UNKNOWN';

  case iStatus of
    0: sResult := 'NON_OPERATIONAL';
    1: sResult := 'UNREACHABLE';
    2: sResult := 'DISCONNECTED';
    3: sResult := 'CONNECTING';
    4: sResult := 'CONNECTED';
    5: sResult := 'OPERATIONAL';
  end;

  Result := sResult;
end;

end.

Para usar esta unidad desde otra unidad, creé la siguiente función, que completó un tipo personalizado llamado TAdapterInfo (declarado en mi unidad principal):

type
  TAdapterInfo = array of record
    dwIndex:    longint;
    dwType:     longint;
    dwMtu:      longint;
    dwSpeed:    extended;
    dwPhysAddrLen: longint;
    bPhysAddr:  string;
    dwAdminStatus: longint;
    dwOperStatus: longint;
    dwLastChange: longint;
    dwInOctets: longint;
    dwInUcastPkts: longint;
    dwInNUcastPkts: longint;
    dwInDiscards: longint;
    dwInErrors: longint;
    dwInUnknownProtos: longint;
    dwOutOctets: longint;
    dwOutUcastPkts: longint;
    dwOutNUcastPkts: longint;
    dwOutDiscards: longint;
    dwOutErrors: longint;
    dwOutQLen:  longint;
    dwDescrLen: longint;
    bDescr:     string;
    sIpAddress: string;
    sIpMask:    string;
  end;

//////////

function Get_EthernetAdapterDetail(var AdapterDataFound: TAdapterInfo): boolean;
var
  pIfTable: ^_IfTable;
  pIpTable: ^_IpAddrTable;
  ifTableSize, ipTableSize: longint;
  tmp:      string;
  i, j, k, m: integer;
  ErrCode:  longint;
  sAddr, sMask: in_addr;
  IPAddresses, IPMasks: TStringList;
  sIPAddressLine, sIPMaskLine: string;
  bResult:  boolean;
begin
  bResult  := True; //default return value
  pIfTable := nil;
  pIpTable := nil;

  IPAddresses := TStringList.Create;
  IPMasks     := TStringList.Create;

  try
    // First: just get the buffer size.
    // TableSize returns the size needed.
    ifTableSize := 0; // Set to zero so the GetIfTabel function
    // won't try to fill the buffer yet,
    // but only return the actual size it needs.
    GetIfTable(pIfTable, ifTableSize, 1);
    if (ifTableSize < SizeOf(MIB_IFROW) + Sizeof(longint)) then
    begin
      bResult := False;
      Result  := bResult;
      Exit; // less than 1 table entry?!
    end;

    ipTableSize := 0;
    GetIpAddrTable(pIpTable, ipTableSize, 1);
    if (ipTableSize < SizeOf(MIB_IPADDRROW) + Sizeof(longint)) then
    begin
      bResult := False;
      Result  := bResult;
      Exit; // less than 1 table entry?!
    end;

    // Second:
    // allocate memory for the buffer and retrieve the
    // entire table.
    GetMem(pIfTable, ifTableSize);
    ErrCode := GetIfTable(pIfTable, ifTableSize, 1);

    if ErrCode <> ERROR_SUCCESS then
    begin
      bResult := False;
      Result  := bResult;
      Exit; // OK, that did not work. 
      // Not enough memory i guess.
    end;

    GetMem(pIpTable, ipTableSize);
    ErrCode := GetIpAddrTable(pIpTable, ipTableSize, 1);

    if ErrCode <> ERROR_SUCCESS then
    begin
      bResult := False;
      Result  := bResult;
      Exit;
    end;

    for k := 1 to pIpTable^.dwNumEntries do
    begin
      sAddr.S_addr := pIpTable^.table[k].dwAddr;
      sMask.S_addr := pIpTable^.table[k].dwMask;

      sIPAddressLine := Format('0x%8.8x', [(pIpTable^.table[k].dwIndex)]) +
        '=' + Format('%s', [inet_ntoa(sAddr)]);
      sIPMaskLine    := Format('0x%8.8x', [(pIpTable^.table[k].dwIndex)]) +
        '=' + Format('%s', [inet_ntoa(sMask)]);

      IPAddresses.Add(sIPAddressLine);
      IPMasks.Add(sIPMaskLine);
    end;

    SetLength(AdapterDataFound, pIfTable^.nRows); //initialize the array or records
    for i := 1 to pIfTable^.nRows do
      try
        //if pIfTable^.ifRow[i].dwType=MIB_IF_TYPE_ETHERNET then
        //begin
        m := i - 1;
        AdapterDataFound[m].dwIndex := 4;//(pIfTable^.ifRow[i].dwIndex);
        AdapterDataFound[m].dwType := (pIfTable^.ifRow[i].dwType);
        AdapterDataFound[m].dwIndex := (pIfTable^.ifRow[i].dwIndex);
        AdapterDataFound[m].sIpAddress :=
          IPAddresses.Values[Format('0x%8.8x', [(pIfTable^.ifRow[i].dwIndex)])];
        AdapterDataFound[m].sIpMask :=
          IPMasks.Values[Format('0x%8.8x', [(pIfTable^.ifRow[i].dwIndex)])];
        AdapterDataFound[m].dwMtu := (pIfTable^.ifRow[i].dwMtu);
        AdapterDataFound[m].dwSpeed := (pIfTable^.ifRow[i].dwSpeed);
        AdapterDataFound[m].dwAdminStatus := (pIfTable^.ifRow[i].dwAdminStatus);
        AdapterDataFound[m].dwOperStatus := (pIfTable^.ifRow[i].dwOperStatus);
        AdapterDataFound[m].dwInUcastPkts := (pIfTable^.ifRow[i].dwInUcastPkts);
        AdapterDataFound[m].dwInNUcastPkts := (pIfTable^.ifRow[i].dwInNUcastPkts);
        AdapterDataFound[m].dwInDiscards := (pIfTable^.ifRow[i].dwInDiscards);
        AdapterDataFound[m].dwInErrors := (pIfTable^.ifRow[i].dwInErrors);
        AdapterDataFound[m].dwInUnknownProtos := (pIfTable^.ifRow[i].dwInUnknownProtos);
        AdapterDataFound[m].dwOutNUcastPkts := (pIfTable^.ifRow[i].dwOutNUcastPkts);
        AdapterDataFound[m].dwOutUcastPkts := (pIfTable^.ifRow[i].dwOutUcastPkts);
        AdapterDataFound[m].dwOutDiscards := (pIfTable^.ifRow[i].dwOutDiscards);
        AdapterDataFound[m].dwOutErrors := (pIfTable^.ifRow[i].dwOutErrors);
        AdapterDataFound[m].dwOutQLen := (pIfTable^.ifRow[i].dwOutQLen);
        AdapterDataFound[m].bDescr := (pIfTable^.ifRow[i].bDescr);

        tmp := '';
        for j := 0 to pIfTable^.ifRow[i].dwPhysAddrLen - 1 do
        begin
          if Length(tmp) > 0 then
            tmp := tmp + '-' + format('%.2x', [pIfTable^.ifRow[i].bPhysAddr[j]])
          else
            tmp := tmp + format('%.2x', [pIfTable^.ifRow[i].bPhysAddr[j]]);
        end;

        if Length(tmp) > 0 then
        begin
          AdapterDataFound[m].bPhysAddr := tmp;
        end;
      except
        bResult := False;
        Result  := bResult;
        Exit;
      end;
  finally
    if Assigned(pIfTable) then
    begin
      FreeMem(pIfTable, ifTableSize);
    end;

    FreeAndNil(IPMasks);
    FreeAndNil(IPAddresses);
  end;

  Result := bResult;
end;

En una nota al margen, también utilicé esta unidad y casi el mismo código para crear un duplicado de ifconfig -a , que se puede encontrar en github . Principalmente lo hice como un ejercicio para enseñarme a mí mismo cómo realizar esta tarea.

Otros consejos

uses WinInet;

function IsConnected: boolean;
const
  // local system uses a modem to connect to the Internet.
  INTERNET_CONNECTION_MODEM      = 1;
  // local system uses a local area network to connect to the Internet.
  INTERNET_CONNECTION_LAN        = 2;
  // local system uses a proxy server to connect to the Internet.
  INTERNET_CONNECTION_PROXY      = 4;
  // local system's modem is busy with a non-Internet connection.
  INTERNET_CONNECTION_MODEM_BUSY = 8;

var
  dwConnectionTypes : DWORD;
begin
  dwConnectionTypes := INTERNET_CONNECTION_MODEM +
                       INTERNET_CONNECTION_LAN +
                       INTERNET_CONNECTION_PROXY;
  Result := InternetGetConnectedState(@dwConnectionTypes,0);
end;

Mire InternetGetConnectedState en WinINet.

Algunas aplicaciones también pueden sondear un servidor conocido y no hacer nada hasta que obtengan una conexión válida.

Aquí hay un ejemplo práctico de cómo usar la unidad auxiliar. Es de un pequeño proyecto que escribí para emular "ifconfig -a". Este es un proyecto de aplicación de consola.

program ifconfig;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Classes,
  Winsock,
  uAdapterInfo in 'uAdapterInfo.pas';

type
  TAdapterInfo = array of record
    dwIndex:    longint;
    dwType:     longint;
    dwMtu:      longint;
    dwSpeed:    extended;
    dwPhysAddrLen: longint;
    bPhysAddr:  string;
    dwAdminStatus: longint;
    dwOperStatus: longint;
    dwLastChange: longint;
    dwInOctets: longint;
    dwInUcastPkts: longint;
    dwInNUcastPkts: longint;
    dwInDiscards: longint;
    dwInErrors: longint;
    dwInUnknownProtos: longint;
    dwOutOctets: longint;
    dwOutUcastPkts: longint;
    dwOutNUcastPkts: longint;
    dwOutDiscards: longint;
    dwOutErrors: longint;
    dwOutQLen:  longint;
    dwDescrLen: longint;
    bDescr:     string;
    sIpAddress: string;
    sIpMask:    string;
  end;




  function Get_EthernetAdapterDetail(var AdapterDataFound: TAdapterInfo): boolean;
  var
    pIfTable: ^_IfTable;
    pIpTable: ^_IpAddrTable;
    ifTableSize, ipTableSize: longint;
    tmp:      string;
    i, j, k, m: integer;
    ErrCode:  longint;
    sAddr, sMask: in_addr;
    IPAddresses, IPMasks: TStringList;
    sIPAddressLine, sIPMaskLine: string;
    bResult:  boolean;
  begin
    bResult  := True; //default return value
    pIfTable := nil;
    pIpTable := nil;

    IPAddresses := TStringList.Create;
    IPMasks     := TStringList.Create;

    try
      // First: just get the buffer size.
      // TableSize returns the size needed.
      ifTableSize := 0; // Set to zero so the GetIfTabel function
      // won't try to fill the buffer yet, 
      // but only return the actual size it needs.
      GetIfTable(pIfTable, ifTableSize, 1);
      if (ifTableSize < SizeOf(MIB_IFROW) + Sizeof(longint)) then
      begin
        bResult := False;
        Result := bResult;
        Exit; // less than 1 table entry?!
      end;

      ipTableSize := 0;
      GetIpAddrTable(pIpTable, ipTableSize, 1);
      if (ipTableSize < SizeOf(MIB_IPADDRROW) + Sizeof(longint)) then
      begin
        bResult := False;
        Result := bResult;
        Exit; // less than 1 table entry?!
      end;

      // Second:
      // allocate memory for the buffer and retrieve the 
      // entire table.
      GetMem(pIfTable, ifTableSize);
      ErrCode := GetIfTable(pIfTable, ifTableSize, 1);

      if ErrCode <> ERROR_SUCCESS then
      begin
        bResult := False;
        Result := bResult;
        Exit; // OK, that did not work. 
        // Not enough memory i guess.
      end;

      GetMem(pIpTable, ipTableSize);
      ErrCode := GetIpAddrTable(pIpTable, ipTableSize, 1);

      if ErrCode <> ERROR_SUCCESS then
      begin
        bResult := False;
        Result := bResult;
        Exit;
      end;

      for k := 1 to pIpTable^.dwNumEntries do
      begin
        sAddr.S_addr := pIpTable^.table[k].dwAddr;
        sMask.S_addr := pIpTable^.table[k].dwMask;

        sIPAddressLine := Format('0x%8.8x', [(pIpTable^.table[k].dwIndex)]) +
          '=' + Format('%s', [inet_ntoa(sAddr)]);
        sIPMaskLine    := Format('0x%8.8x', [(pIpTable^.table[k].dwIndex)]) +
          '=' + Format('%s', [inet_ntoa(sMask)]);

        IPAddresses.Add(sIPAddressLine);
        IPMasks.Add(sIPMaskLine);
      end;

      SetLength(AdapterDataFound, pIfTable^.nRows); //initialize the array or records
      for i := 1 to pIfTable^.nRows do
        try
          //if pIfTable^.ifRow[i].dwType=MIB_IF_TYPE_ETHERNET then
          //begin
          m := i - 1;
          AdapterDataFound[m].dwIndex := 4;//(pIfTable^.ifRow[i].dwIndex);
          AdapterDataFound[m].dwType := (pIfTable^.ifRow[i].dwType);
          AdapterDataFound[m].dwIndex := (pIfTable^.ifRow[i].dwIndex);
          AdapterDataFound[m].sIpAddress :=
            IPAddresses.Values[Format('0x%8.8x', [(pIfTable^.ifRow[i].dwIndex)])];
          AdapterDataFound[m].sIpMask :=
            IPMasks.Values[Format('0x%8.8x', [(pIfTable^.ifRow[i].dwIndex)])];
          AdapterDataFound[m].dwMtu := (pIfTable^.ifRow[i].dwMtu);
          AdapterDataFound[m].dwSpeed := (pIfTable^.ifRow[i].dwSpeed);
          AdapterDataFound[m].dwAdminStatus := (pIfTable^.ifRow[i].dwAdminStatus);
          AdapterDataFound[m].dwOperStatus := (pIfTable^.ifRow[i].dwOperStatus);
          AdapterDataFound[m].dwInUcastPkts := (pIfTable^.ifRow[i].dwInUcastPkts);
          AdapterDataFound[m].dwInNUcastPkts := (pIfTable^.ifRow[i].dwInNUcastPkts);
          AdapterDataFound[m].dwInDiscards := (pIfTable^.ifRow[i].dwInDiscards);
          AdapterDataFound[m].dwInErrors := (pIfTable^.ifRow[i].dwInErrors);
          AdapterDataFound[m].dwInUnknownProtos := (pIfTable^.ifRow[i].dwInUnknownProtos);
          AdapterDataFound[m].dwOutNUcastPkts := (pIfTable^.ifRow[i].dwOutNUcastPkts);
          AdapterDataFound[m].dwOutUcastPkts := (pIfTable^.ifRow[i].dwOutUcastPkts);
          AdapterDataFound[m].dwOutDiscards := (pIfTable^.ifRow[i].dwOutDiscards);
          AdapterDataFound[m].dwOutErrors := (pIfTable^.ifRow[i].dwOutErrors);
          AdapterDataFound[m].dwOutQLen := (pIfTable^.ifRow[i].dwOutQLen);
          AdapterDataFound[m].bDescr := (pIfTable^.ifRow[i].bDescr);

          tmp := '';
          for j := 0 to pIfTable^.ifRow[i].dwPhysAddrLen - 1 do
          begin
            if Length(tmp) > 0 then
              tmp := tmp + '-' + format('%.2x', [pIfTable^.ifRow[i].bPhysAddr[j]])
            else
              tmp := tmp + format('%.2x', [pIfTable^.ifRow[i].bPhysAddr[j]]);
          end;

          if Length(tmp) > 0 then
          begin
            AdapterDataFound[m].bPhysAddr := tmp;
          end;
        except
          bResult := False;
          Result := bResult;
          Exit;
        end;
    finally
      if Assigned(pIfTable) then
      begin
        FreeMem(pIfTable, ifTableSize);
      end;

      FreeAndNil(IPMasks);
      FreeAndNil(IPAddresses);
    end;

    Result := bResult;
  end;



var
  AdapterData: TAdapterInfo;
  i: integer;
begin
  try
    WriteLn('');
    if Get_EthernetAdapterDetail(AdapterData) then
    begin
      for i := 0 to Length(AdapterData) - 1 do
      begin
        WriteLn(Format('0x%8.8x', [AdapterData[i].dwIndex]));
        WriteLn('"' + AdapterData[i].bDescr + '"');
        Write(Format(#9 + 'Link encap: %s ', [Get_if_type(AdapterData[i].dwType)]));

        if Length(AdapterData[i].bPhysAddr) > 0 then
          Write('HWaddr: ' + AdapterData[i].bPhysAddr);

        Write(#13 + #10 + #9 + 'inet addr:' + AdapterData[i].sIpAddress);
        WriteLn(' Mask: ' + AdapterData[i].sIpMask);
        WriteLn(Format(#9 + 'MTU: %d Speed:%.2f Mbps', [AdapterData[i].dwMtu,
          (AdapterData[i].dwSpeed) / 1000 / 1000]));
        Write(#9 + 'Admin status:' + Get_if_admin_status(AdapterData[i].dwAdminStatus));
        WriteLn(' Oper status:' + Get_if_oper_status(AdapterData[i].dwOperStatus));
        WriteLn(#9 + Format('RX packets:%d dropped:%d errors:%d unkown:%d',
          [AdapterData[i].dwInUcastPkts + AdapterData[i].dwInNUcastPkts,
          AdapterData[i].dwInDiscards, AdapterData[i].dwInErrors,
          AdapterData[i].dwInUnknownProtos]));
        WriteLn(#9 + Format('TX packets:%d dropped:%d errors:%d txqueuelen:%d',
          [AdapterData[i].dwOutUcastPkts + AdapterData[i].dwOutNUcastPkts,
          AdapterData[i].dwOutDiscards, AdapterData[i].dwOutErrors,
          AdapterData[i].dwOutQLen]));

        WriteLn('');
      end;
    end
    else
    begin
      WriteLn(#13+#10+'*** Error retrieving adapter information');
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top