Определить запуск сети завершен - PullRequest
0 голосов
/ 17 июня 2020

У меня есть приложение, работающее на встроенной версии Windows 7. Оболочка Explorer заменяется Autohotkey, который затем запускает наше приложение.

Проблема в том, что наше приложение запускается слишком быстро, раньше Windows 'Сеть завершила запуск. Это приводит к тому, что запоминаемые сетевые интерфейсы не всегда доступны при запуске приложения. *

Есть ли гарантированный способ определить, что все доступные сети работают (надеюсь, проще, чем моя попытка)?

// STEP 1 Find the list of ethernet adapters that have a mac address
c := net_interfaces.RefreshAdapters;
tick_count := GetTickCount + 2000;
while (c < 11) and (GetTickCount < tick_count) do
begin
  Sleep(100);
  c := net_interfaces.RefreshAdapters;
end;
c := net_interfaces.RefreshAdapters(false);
LogMsg('Ethernet adapters found: '+c.ToString);

// STEP 2 Figure out what adapters are physically connected
tick_count := GetTickCount + 5000;
while (GetAdapterCount(false) < expected_interface_count) and (GetTickCount < tick_count) do
  Sleep(100);
expected_interface_count := GetAdapterCount(false);
LogMsg('Ethernet adapters connected: ' + expected_interface_count.ToString);

// STEP 3 Populate the interface table with the correct number
tick_count := GetTickCount + 5000;
while (net_interfaces.Count < (expected_interface_count+1)) and (GetTickCount < tick_count) do
begin
  net_interfaces.populate;
  Sleep(100);
end;

// STEP 4 Check to see if we are waiting for DHCP
if net_interfaces.NetworkWaitingOnDHCP then
begin
  fSplash.StetPB('Waiting on DHCP to be assigned');
  tick_count := GetTickCount + 10000;
  while (net_interfaces.NetworkWaitingOnDHCP) and (GetTickCount < tick_count) do
  begin
    net_interfaces.populate;
    Sleep(100);
  end;
end;
if net_interfaces.NetworkWaitingOnDHCP then
  LogMsg('No DHCP address was assigned');

// STEP 5 Repopulate the interface table
net_interfaces.populate;

Шаг 1. Процедура «RefreshAdapters» использует код, найденный в этом сообщении, используя "GetIfTable". Delphi, как получить все локальные IP-адреса?

Шаг 2. GetAdapterCount использует следующую технику ...

function GetAdapterCount(LogFound: boolean): integer;
var
  oBindObj : IDispatch;
  oNetAdapters, oNetAdapter,
  odnsAddr, oWMIService : OleVariant;
  i, iValue : LongWord;
  oEnum : IEnumVariant;
  oCtx : IBindCtx;
  oMk : IMoniker;
  sFileObj : WideString;
begin
  result := 0;
  sFileObj := 'winmgmts:\\.\root\cimv2';

  OleCheck(CreateBindCtx(0,oCtx));
  OleCheck(MkParseDisplayNameEx(oCtx, PWideChar(sFileObj), i, oMk));
  OleCheck(oMk.BindToObject(oCtx, nil, IUnknown, oBindObj));
  oWMIService := oBindObj;

  oNetAdapters := oWMIService.ExecQuery('SELECT * FROM Win32_NetworkAdapter WHERE PhysicalAdapter=True AND MACAddress IS NOT NULL AND AdapterType IS NOT NULL AND NetConnectionStatus=2');

  oEnum := IUnknown(oNetAdapters._NewEnum) as IEnumVariant;

  while oEnum.Next(1, oNetAdapter, iValue) = 0 do begin
    inc(result);
    if logFound then
      LogMsg('Connected adapters: ' + oNetAdapter.Caption);
    oNetAdapter := Unassigned;
  end;

  odnsAddr := Unassigned;
  oNetAdapters := Unassigned;
  oWMIService := Unassigned;
end;

Шаг 3. " Заполните "список интерфейсов

procedure TInterfaces.populate;
var
  err, BytesRet, i: integer;
  fSocket: TSocket;
  tmpInterfaceItm: TInterfaceItm;

  nNumInterfaces: integer;
  InterfaceList: Array[0..20] of INTERFACE_INFO;
begin
  InitializeWinSock;

  try
    Clear;
    fSocket := Socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
    if fSocket = INVALID_SOCKET then exit
    else
    begin
      err := WSAIoctl(fSocket, SIO_GET_INTERFACE_LIST, Nil, 0, @InterfaceList, sizeof(InterfaceList), @BytesRet, Nil, Nil);
      if err <> SOCKET_ERROR then
      begin
        nNumInterfaces := BytesRet div sizeof(INTERFACE_INFO);
        for i := 0 to nNumInterfaces-1 do
        begin
          tmpInterfaceItm := TInterfaceItm.Create;
          Add(tmpInterfaceItm);

          tmpInterfaceItm.in_interface_address       := Psockaddr_in(@InterfaceList[i].iiAddress)^.sin_addr;
          tmpInterfaceItm.in_interface_mask          := Psockaddr_in(@InterfaceList[i].iiNetmask)^.sin_addr;
          tmpInterfaceItm.in_interface_broadcast     := CalculateBroadcastAddr(Psockaddr_in(@InterfaceList[i].iiAddress)^.sin_addr,
                                                                           Psockaddr_in(@InterfaceList[i].iiNetmask)^.sin_addr);
          tmpInterfaceItm.in_interface_sys_broadcast := Psockaddr_in(@InterfaceList[i].iiBroadcastAddress)^.sin_addr;

          tmpInterfaceItm.interface_address   := string(inet_ntoa(tmpInterfaceItm.in_interface_address));
          tmpInterfaceItm.interface_mask      := string(inet_ntoa(tmpInterfaceItm.in_interface_mask));
          tmpInterfaceItm.interface_broadcast := string(inet_ntoa(tmpInterfaceItm.in_interface_broadcast));
        end;
      end;
      CloseSocket(fSocket);
    end;
  finally
     //UninitializeWinSock;
  end;
end;

Шаг 4." NetworkWaitingOnDHCP "Проверьте, ждем ли мы DHCP

function TInterfaces.NetworkWaitingOnDHCP: Boolean;
var
  i, j: Integer;
  isUp: boolean;
begin
  result := false;
  for i := 0 to Count-1 do
  begin
    if (copy(trim(items[i].interface_address), 1, 7) = '169.254') then
    begin
      isUp := false;
      net_interfaces.RefreshAdapters(false);
      for j := 0 to High(Adapters) do
      begin
        if Adapters[j].sIpAddress = items[i].interface_address then
        begin
          isUp := Adapters[j].dwOperStatus > MIB_IF_OPER_STATUS_DISCONNECTED;
          break;
        end;
      end;

      if isUp then
      begin
        result := true;
        break;
      end;
    end;
  end;
end;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...