Detect an internet connection activation with Delphi

后端 未结 4 503
不思量自难忘°
不思量自难忘° 2020-12-01 05:45

I\'ve been using a 3G wireless card for a while and every time I connect, my anti-virus fires up the updates.

I\'m wondering what is the Win32 API set of functions t

4条回答
  •  渐次进展
    2020-12-01 06:19

    I worked on a project to run a user's logon script whenever they connected our network over VPN. To do this, I wrote a helper unit that retrieves adapter info and stores it into a simple record.

    I then setup up a registry notification, see here for how to do that in Delphi

    The registry notification was on HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces. This notification event fires every time Windows obtains a new IP address, or makes any type of change to an adapters connection information. When this event fired, I called the function (in the code below) to retrieve updated information about the adapter. I compared this new information to my previously recorded information...meaning I had to save the previous adapter info query in order to know if something had changed.

    Anyhow, here is my helper unit:

    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.
    

    To use this unit from another unit, I created the following function, which populated a custom type called TAdapterInfo (declared in my main unit):

    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;
    

    On a completely side note, I also used this unit and almost exact same code to create a duplicate of ifconfig -a, which can be found on github. I mainly did it as an exercise in teaching myself how to accomplish this task.

提交回复
热议问题