Detect an internet connection activation with Delphi

后端 未结 4 488
不思量自难忘°
不思量自难忘° 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.

    0 讨论(0)
  • 2020-12-01 06:25
    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;
    
    0 讨论(0)
  • 2020-12-01 06:36

    Here's a working example of how to use the helper unit. It is from a small project I wrote to emulate "ifconfig -a". This is a console application project.

    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.
    
    0 讨论(0)
  • 2020-12-01 06:43

    Look at InternetGetConnectedState in WinINet.

    Some applications might also poll for a known server and not do anything until they get a valid connection.

    0 讨论(0)
提交回复
热议问题