【问题标题】:Detect an internet connection activation with Delphi使用 Delphi 检测 Internet 连接激活
【发布时间】:2010-09-24 11:05:55
【问题描述】:

我使用 3G 无线网卡已经有一段时间了,每次连接时,我的防病毒软件都会启动更新。

我想知道我可以使用哪些 Win32 API 函数集来获得通知或查询有关 Internet 连接即将到来的事件?

是否已经有一组用于 Delphi 的移植标头?

【问题讨论】:

  • 定义互联网连接?什么是互联网?
  • 我认为这将是一个网络接口,但我真的不知道反病毒如何探测它。

标签: delphi winapi wininet internet-connection


【解决方案1】:

查看 WinINet 中的 InternetGetConnectedState。

某些应用程序还可能轮询已知服务器,并且在获得有效连接之前不执行任何操作。

【讨论】:

    【解决方案2】:
    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;
    

    【讨论】:

    • 是的。这就是我使用的。不过,我不确定它是否 100% 可靠。
    【解决方案3】:

    我参与了一个项目,只要用户通过 VPN 连接我们的网络,就可以运行他们的登录脚本。为此,我编写了一个辅助单元来检索适配器信息并将其存储到一个简单的记录中。

    然后我设置了一个注册表通知,see here for how to do that in Delphi

    注册通知在HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces。每次 Windows 获得新的 IP 地址或对适配器连接信息进行任何类型的更改时,都会触发此通知事件。当此事件触发时,我调用了该函数(在下面的代码中)以检索有关适配器的更新信息。我将这个新信息与我之前记录的信息进行了比较...这意味着我必须保存之前的适配器信息查询才能知道是否发生了变化。

    总之,这是我的辅助单元:

    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.
    

    为了在另一个单元中使用这个单元,我创建了以下函数,它填充了一个名为 TAdapterInfo 的自定义类型(在我的主单元中声明):

    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;
    

    顺便说一句,我还使用这个单元和几乎完全相同的代码来创建ifconfig -a 的副本,其中can be found on github。我这样做主要是为了自学如何完成这项任务。

    【讨论】:

    • 您的代码在此行崩溃(范围检查错误):for k := 1 to pIpTable^.dwNumEntries do...
    • 一位评论者通过电子邮件向我发送了一个修复(我在此处更新):“在我将类型中的“wszName”和“bDescr”的声明从“char”更改为“ansichar”之后,它的措辞很好“MIB_IFROW”。我在 Win 10 上的 Delphi 10.1 中使用了你的单元。”
    【解决方案4】:

    这是一个如何使用辅助单元的工作示例。它来自我为模拟“ifconfig -a”而编写的一个小项目。这是一个控制台应用程序项目。

    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.
    

    【讨论】:

    • 您的代码在此行崩溃(范围检查错误):for k := 1 to pIpTable^.dwNumEntries do...
    • 现在应该修复了。我最初使用 Delphi 2007 编译(并在近 10 年前编写),但评论者发现并修复了该错误并说它在 Delphi 10.1 Berlin 中编译。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-11
    • 1970-01-01
    • 2013-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多