Убедитесь, что компьютер Windows через Ethernet через C ++

Поэтому я попытался рассмотреть несколько разных ответов для этого. Тот, который, как я думал, может пообещать, был следующим:

Как проверить тип сетевого интерфейса: Ethernet или Wireless в Windows с использованием Qt?

Однако я не слишком много знаю о работе в сети или даже о Windows. Лично я не могу понять большую часть документации Microsoft на своих сайтах. Я пробовал такие вещи, как INetworkConnection , NativeWiFi и т. Д. Но либо они не делают то, что я хочу, либо просто не могу понять, как это сделать из доступной документации.

С учетом сказанного я хотел бы использовать C ++, чтобы проверить, подключено ли устройство, на котором эта программа работает, через Интернет через кабель Ethernet. В принципе, я хочу сделать следующее:

  • Если компьютер подключен только к беспроводной сети, запустите программу
  • Если компьютер подключен только к проводному, не запускайте программу
  • Если компьютер подключен к проводной и беспроводной сети, не запускайте программу

Однако проблема в том, что я не знаю, как проверить, подключено ли устройство к Ethernet. Есть ли способ сделать это? Я НЕ использую QT. Спасибо!


EDIT: Я должен также включить то, что я пробовал до сих пор.

Я попытался использовать GetAdaptersInfo и получить характер Type из PIP_ADAPTER_INFO переменной PIP_ADAPTER_INFO , но это всегда дает мне Unknown type 71 будь я на Ethernet или нет.

Документация для этого GetAdaptersInfo находится здесь: https://msdn.microsoft.com/en-us/library/aa365917%28VS.85%29.aspx

благодаря


EDIT 2: Вот код, который я использовал для GetAdaptersInfo

 bool is_on_ethernet{ PIP_ADAPTER_INFO pAdapterInfo; PIP_ADAPTER_INFO pAdapter = NULL; DWORD dwRetVal = 0; UINT i; struct tm newtime; char buffer[32]; errno_t error; ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO); pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO)); if(pAdapterInfo == NULL) printf("Error allocating memory need to call GetAdaptersInfo"); if(GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW){ free(pAdapterInfo); pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen); } if((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR){ pAdapter = pAdapterInfo; switch(pAdapter->Type){ case MIB_IF_TYPE_OTHER: printf("Other\n"); return false; break; case MIB_IF_TYPE_ETHERNET: printf("Ethernet\h"); return true; break; case MIB_IF_TYPE_TOKENRING: printf("Token Ring\n"); return false; break; case MIB_IF_TYPE_FDDI printf("FDDI\n"); return false; break; case MIB_IF_TYPE_PPP printf("PPP\n"); return false; break; case MIB_IF_TYPE_LOOPBACK printf("Lookback\n"); return false; break; case MIB_IF_TYPE_SLIP printf("Slip\n"); return false; break; default printf("Unknown type %ld\n\n", pAdapter->Type); return false; break; } } if(pAdapterInfo) free(pAdapterInfo); return false; } 

Ваша проблема несколько сложна, так как очень сложно получить «текущий» сетевой адаптер – windows маршрутизируют пакеты в зависимости от конфигурации сетевого адаптера и достижимости назначения, поэтому ваш «текущий» адаптер может меняться в любое время … но так как вы уже знают, как получить IP-адреса и MAC-адреса («аппаратный адрес») доступных адаптеров, вы можете просто использовать свой хак для получения MAC для вашего текущего IP-адреса и фильтрации / поиска внутри моей второй функции! Поле «PhysicalAddress» – это то, что вы ищете, это MAC-адрес

Я сделал опыт, что единственный, несколько надежный способ сделать это – через GetIfTable и GetIfTable2 , первый возвращает некоторую поверхностную информацию об adpater, а последняя обеспечивает большую детализацию . Вот пример реализации, поскольку он использует подробную функцию, которую вы также можете запросить для адаптеров WLAN:

 vector* getDevices(NDIS_PHYSICAL_MEDIUM type) { vector *v = new vector(); PMIB_IF_TABLE2 table = NULL; if(GetIfTable2Ex(MibIfTableRaw, &table) == NOERROR && table) { UINT32 i = 0; for(; i < table->NumEntries; i++) { MIB_IF_ROW2 row; ZeroMemory(&row, sizeof(MIB_IF_ROW2)); row.InterfaceIndex = i; if(GetIfEntry2(&row) == NOERROR) { if(row.PhysicalMediumType == type) { v->push_back(row); } } } FreeMibTable(table); } return v; } 

Теперь все, что вам нужно сделать, это перебрать список и отфильтровать отключенные адаптеры и многое другое:

 vector* wlan = getDevices(NdisPhysicalMediumNative802_11); //WLAN adapters //see https://msdn.microsoft.com/en-us/library/windows/desktop/aa814491(v=vs.85).aspx, "PhysicalMediumType" for a full list for(auto &row : *v) { //do some additional filtering, this needs to be changed for non-WLAN if( row.TunnelType == TUNNEL_TYPE_NONE && row.AccessType != NET_IF_ACCESS_LOOPBACK && row.Type == IF_TYPE_IEEE80211 && row.InterfaceAndOperStatusFlags.HardwareInterface == TRUE) { //HERE BE DRAGONS! } } 

Теперь его довольно легко сгенерировать списки адаптеров WLAN и адаптеров, отличных от WLAN (см. Комментарий во второй функции) , найти свой текущий MAC и сделать вывод, что он проводной или беспроводной – но имейте в виду, что эти списки могут перекрываться, поскольку 802.11 в основном является расширенная версия 802.3, но 802.3 не включает 802.11 (с ее расширением), поэтому вам понадобится крошечный бит if / else, чтобы разделить WLAN от не-WLAN-адаптеров.

Вы также можете использовать WlanEnumInterfaces для получения всех адаптеров WLAN, но это в основном то же самое, что и использование вышеуказанной функции с параметром NdisPhysicalMediumNative802_11

Итак, во-первых, большое спасибо пользователю @ Nighthawk441 за то, что указали мне в правильном направлении. Без этого пользователя я бы наверняка не придумал решение.

Тем не менее, решение, которое я имею сейчас, в лучшем случае – это взломать. Кажется, это работает, но я не думаю, что это даже близко к лучшему варианту. Таким образом, я оставлю это в качестве ответа, но я не буду принимать его на некоторое время, если будет найден лучший ответ. Я также очень открыт для любых комментариев, которые могут быть у каждого, кто имеет отношение к этому ответу.

Короче говоря, то, что я сделал, я зациклился на всех адаптерах из GetAdaptersInfo . Чтобы узнать, подключен ли адаптер, я сравнил IP-адрес адаптера со строкой "0.0.0.0" , как если бы это было нечто иное, чем это я чувствовал, что было бы безопасно сказать, что адаптер был подключен. Итак, без дальнейших церемоний, вот код, который я реализовал.

 bool is_on_ethernet(){ PIP_ADAPTER_INFO pAdapterInfo; PIP_ADAPTER_INFO pAdapter = NULL; DWORD dwRetVal = 0; UINT i; struct tm newtime; char buffer[32]; errno_t error; ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO); pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO)); if(pAdapterInfo == NULL) printf("Error allocating memory needed to call GetAdaptersInfo"); if(GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW){ free(pAdapterInfo); pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen); } if((dwRetValue = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR){ do{ pAdapter = pAdapterInfo; string ip_string = pAdapter->IpAddressList.IpAddress.String; switch(pAdapter->Type){ case MIB_IF_TYPE_OTHER: printf("Other\n"); break; ... case MIB_IF_TYPE_ETHERNET: printf("Ethernet\n"); //new code if(ip_string.compare("0.0.0.0") != 0){ free(pAdapterInfo); return true; } break; default: printf("Unknown type %ld\n", pAdapter->Type); break; } }while(pAdapterInfo = pAdapterInfo->Next); } if(pAdapterInfo) free(pAdapterInfo); return false; } 

Глядя на эту ссылку, я действительно помог мне:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa365819%28v=vs.85%29.aspx

Так что спасибо Nighthawk за предоставление этой информации мне. Надеюсь, это поможет кому-то еще! Если у кого есть какие-либо комментарии или какие-либо другие ответы, не стесняйтесь публиковать их! Благодаря!