2015-08-14 133 views
3

因此,我試圖尋找幾個不同的答案。一,我認爲可能有希望是這樣的一個:檢查以太網上的Windows計算機是否通過C++

How to check network interface type is Ethernet or Wireless on Windows using Qt?

不過,我真的不知道太多關於網絡,甚至有關Windows。就我個人而言,我無法理解他們網站上的大部分Microsoft文檔。我嘗試了一些東西,比如INetworkConnection,NativeWiFi等。但是他們沒有做我想做的事,或者我無法弄清楚如何從可用的文檔中做到這一點。

有了這樣說,我想用C++,以檢查是否該程序正在運行的設備連接到經由以太網電纜互聯網。基本上,我要做到以下幾點:

  • 如果計算機連接到無線只,運行程序
  • 如果計算機連接到有線只,不運行程序
  • 如果計算機連接到有線和無線,不要運行程序

但是,問題是我不知道如何檢查設備是否有以太網連接。有沒有辦法做到這一點?我沒有使用QT。謝謝!編輯:我還應該包括我到目前爲止嘗試過的東西。

我嘗試使用GetAdaptersInfo和獲取Type特質從PIP_ADAPTER_INFO變量類型,但總是給我Unknown type 71無論我是在以太網或沒有。

GetAdaptersInfo的文檔是在這裏: https://msdn.microsoft.com/en-us/library/aa365917%28VS.85%29.aspx

感謝


編輯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; 
} 
+0

你有你試圖使用GetAdaptersInfo的示例代碼?我做的是 –

+0

;我現在將其添加爲編輯。對不起,不包括! –

+0

@ Nighthawk441好的 - 我已經包含代碼作爲編輯。再次,對於之前缺乏代碼感到抱歉!感謝您評論:) –

回答

1

你的問題是,因爲它可以很複雜,以獲得「當前」網絡適配器有些困難---這取決於網絡適配器配置和目的地的可達性窗口的分組路由讓你的「當前」適配器可隨時更改.. 。但既然你已經知道了如何獲取可用適配器的IP和MAC的(「硬件地址」),你可以簡單地使用你的黑客獲取一個MAC您當前的IP和過濾器/搜索我的第二個函數中吧!字段「PhysicalAddress」是你在找什麼,那該MAC地址

我已經做了體驗,這樣做的唯一的,有點可靠的方法是通過GetIfTableGetIfTable2,前者的回報有所superficial adpater info,後者提供了很好的detail。 繼承人示例實現,因爲它使用的詳細功能,您還可以查詢WLAN適配器:

vector<MIB_IF_ROW2>* getDevices(NDIS_PHYSICAL_MEDIUM type) 
    {  
     vector<MIB_IF_ROW2> *v = new vector<MIB_IF_ROW2>(); 
     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<MIB_IF_ROW2>* 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作爲參數上面的函數...

+0

這似乎是一個很好的答案,但不幸的是我有點困惑。一旦我像第二個代碼塊一樣遍歷矢量,行的很多屬性都是相同的。我如何區分無線和有線?我如何知道用戶是否連接到以太網?我試過使用物理地址屬性,但這些似乎沒有給我一個MAC地址,所以我不確定要比較的是什麼。對困惑感到抱歉。謝謝! –

+0

好吧,經過一些實驗後,我得到了這個答案的工作。我將if語句更改爲if(row.Type == IF_TYPE_ETHERNET_CSMACD && row.MediaConnectState == MdiaConnectStateConnected),然後在if語句中返回true。非常感謝您的時間和幫助。我現在會接受這個答案。 –

+0

^附錄:我也改變了我發送給'getDevices'函數的參數是'NdisPhysicalMedium802_3' –

0

所以首先代碼,謝謝非常感謝用戶@ 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

所以,謝謝你夜鷹,用於提供信息給我。希望這會幫助別人!如果有人有任何意見或任何其他答案,請隨時發佈!謝謝!

+1

我認爲這應該是C++?這段代碼充滿了令人厭惡的手動內存管理terribadness。 – Puppy

+0

其初學者的嘗試......不審判他還沒有 - 而不是非常詳細指出的缺陷,並提供其如何完成的例子。 – specializt

+0

@Puppy該代碼表面上直接從我在我的答案中提到的MSDN引用中複製。我已經總共添加了一個[免費(...)]聲明。如果內存管理是一個問題,那麼我將不得不轉向並說這是MSDN文檔的問題。 –

相關問題