Visual C++ Tips: 用 IP Helper 获得网络接口的友好名称(Friendly Name)

前面有篇文章:《用 WinPcap 获取网络接口列表》,是通过 WinPcap 库来获得网络接口列表,但是拿到的网络接口名称对于人(Human Being)来说毫无意义,如下图: 

 

 

 实际上我们在 Windows 控制面板(Control Panel)中看到的是网络接口的“友好名称”(Friendly Name),如下: 

 

为了拿到网络接口的“友好名称”,我遍查 MSDN,终于找到了答案。以下是我写的程序示例:

NetworkInformation.h

 1 #ifndef _NetworkInformation_H
 2 #define _NetworkInformation_H
 3 
 4 #include <vector>
 5 #include <winsock2.h>
 6 #include <iphlpapi.h>
 7 
 8 // https://communities.ca.com/thread/241732865
 9 #define MAX_ADAPTER_FriendlyName_LENGTH 65
10 
11 typedef struct
12 {
13     TCHAR AdapterName[MAX_ADAPTER_NAME_LENGTH + 4] = { 0 };
14     TCHAR Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4] = { 0 };
15     TCHAR FriendlyName[MAX_ADAPTER_FriendlyName_LENGTH + 4] = { 0 };
16     GUID NetworkGuid = { 0 };
17     BYTE PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH] = { 0 };
18     DWORD PhysicalAddressLength = 0;
19     union {
20         ULONG Flags;
21         struct {
22             ULONG DdnsEnabled : 1;
23             ULONG RegisterAdapterSuffix : 1;
24             ULONG Dhcpv4Enabled : 1;
25             ULONG ReceiveOnly : 1;
26             ULONG NoMulticast : 1;
27             ULONG Ipv6OtherStatefulConfig : 1;
28             ULONG NetbiosOverTcpipEnabled : 1;
29             ULONG Ipv4Enabled : 1;
30             ULONG Ipv6Enabled : 1;
31             ULONG Ipv6ManagedAddressConfigurationSupported : 1;
32         };
33     };
34     DWORD Mtu = 0;
35     DWORD IfType = 0;
36     IF_OPER_STATUS OperStatus = IfOperStatusUnknown;
37     NET_IF_CONNECTION_TYPE ConnectionType;
38     TUNNEL_TYPE TunnelType= TUNNEL_TYPE_NONE;
39 
40 } IP_AdaptersAddresses;
41 
42 DWORD GetAdaptersAddressesInfo(std::vector<IP_AdaptersAddresses> & adapters_collection);
43 
44 #endif // _NetworkInformation_H

NetworkInformation.cpp

  1 #include "NetworkInformation.h"
  2 
  3 #include <tchar.h>
  4 #include <Windows.h>
  5 
  6 #include <winsock2.h>
  7 #include <iphlpapi.h>
  8 
  9 #pragma comment(lib, "IPHLPAPI.lib")
 10 
 11 #define WORKING_BUFFER_SIZE 81920
 12 
 13 DWORD GetAdaptersAddressesInfo(std::vector<IP_AdaptersAddresses> & adapters_collection)
 14 {
 15     DWORD return_code = NO_ERROR;
 16     adapters_collection.clear();
 17 
 18     // A pointer to a buffer that contains a linked list of IP_ADAPTER_ADDRESSES structures on successful return.
 19     IP_ADAPTER_ADDRESSES * pAdapterAddresses = nullptr;
 20     IP_ADAPTER_ADDRESSES * pCurrAddresses = nullptr;
 21 
 22     // specifies the size of the buffer pointed to by AdapterAddresses.
 23     ULONG sizeOfAdapterAddresses = WORKING_BUFFER_SIZE;
 24 
 25     // Return both IPv4 and IPv6 addresses associated with adapters with IPv4 or IPv6 enabled.
 26     ULONG family = AF_UNSPEC;
 27 
 28     // Return addresses for all NDIS interfaces.
 29     ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
 30 
 31     // This parameter is not currently used, but is reserved for future system use.
 32     PVOID reserved = NULL;
 33 
 34     pAdapterAddresses = (IP_ADAPTER_ADDRESSES *)HeapAlloc(GetProcessHeap(), 0, sizeOfAdapterAddresses);
 35     if (pAdapterAddresses == NULL)
 36     {
 37         return_code = 0xFFFFFFFF;
 38     }
 39 
 40     memset(pAdapterAddresses, 0, sizeOfAdapterAddresses);
 41 
 42     ULONG dwRetVal = GetAdaptersAddresses(family, flags, reserved, pAdapterAddresses, &sizeOfAdapterAddresses);
 43     if (dwRetVal == NO_ERROR)
 44     {
 45         // If successful, output some information from the data we received.
 46         pCurrAddresses = pAdapterAddresses;
 47         while (pCurrAddresses)
 48         {
 49             IP_AdaptersAddresses adapter;
 50 
 51             size_t adapter_name_length = strlen(pCurrAddresses->AdapterName);
 52             for (size_t i = 0; i < adapter_name_length; i++)
 53             {
 54                 adapter.AdapterName[i] = pCurrAddresses->AdapterName[i];
 55             }
 56 
 57             _tcscpy_s(adapter.Description, pCurrAddresses->Description);
 58             _tcscpy_s(adapter.FriendlyName, pCurrAddresses->FriendlyName);
 59             adapter.NetworkGuid = pCurrAddresses->NetworkGuid;
 60 
 61             adapter.PhysicalAddressLength = pCurrAddresses->PhysicalAddressLength;
 62             for (size_t i = 0; i < adapter.PhysicalAddressLength; i++)
 63             {
 64                 adapter.PhysicalAddress[i] = pCurrAddresses->PhysicalAddress[i];
 65             }
 66 
 67             adapter.Flags = pCurrAddresses->Flags;
 68             adapter.Mtu = pCurrAddresses->Mtu;
 69             adapter.IfType = pCurrAddresses->IfType;
 70             adapter.OperStatus = pCurrAddresses->OperStatus;
 71             adapter.ConnectionType = pCurrAddresses->ConnectionType;
 72             adapter.TunnelType = pCurrAddresses->TunnelType;
 73 
 74             adapters_collection.push_back(adapter);
 75             pCurrAddresses = pCurrAddresses->Next;
 76         }
 77     }
 78     else
 79     {
 80         switch (dwRetVal)
 81         {
 82         case ERROR_ADDRESS_NOT_ASSOCIATED:
 83             // An address has not yet been associated with the network endpoint.
 84             // DHCP lease information was available.
 85             break;
 86         case ERROR_BUFFER_OVERFLOW:
 87             // The buffer size indicated by the SizePointer parameter is too small to hold the adapter information or
 88             // AdapterAddresses parameter is NULL.
 89             // The SizePointer parameter returned points to the required size of the buffer to hold the adapter information.
 90             break;
 91         case ERROR_INVALID_PARAMETER:
 92             // One of the parameters is invalid. This error is returned for any of the following conditions: 
 93             // the SizePointer parameter is NULL, the Address parameter is not AF_INET, AF_INET6, or AF_UNSPEC, 
 94             // or the address information for the parameters requested is greater than ULONG_MAX.
 95             break;
 96         case ERROR_NOT_ENOUGH_MEMORY:
 97             // Insufficient memory resources are available to complete the operation.
 98             break;
 99         case ERROR_NO_DATA:
100             // No addresses were found for the requested parameters.
101             break;
102         default:
103             // Use FormatMessage to obtain the message string for the returned error.
104             break;
105         }
106 
107         return_code = dwRetVal;
108     }
109 
110     if (pAdapterAddresses)
111     {
112         HeapFree(GetProcessHeap(), 0, pAdapterAddresses);
113         pAdapterAddresses = nullptr;
114     }
115 
116     return return_code;
117 }

GetNetworkInformation.cpp

 1 // GetNetworkInformation.cpp : Defines the entry point for the console application.
 2 //
 3 
 4 #include <io.h>
 5 #include "NetworkInformation.h"
 6 
 7 int main()
 8 {
 9     std::vector<IP_AdaptersAddresses> adapters_collection;
10     DWORD return_code = GetAdaptersAddressesInfo(adapters_collection);
11     if (return_code == NO_ERROR)
12     {
13         size_t count = adapters_collection.size();
14         for (size_t i = 0; i < count; i++)
15         {
16             _tprintf(_T("%d.\tFriendlyName: %wS\n"), i + 1, adapters_collection[i].FriendlyName);
17             _tprintf(_T("\tAdapterName : %wS\n"), adapters_collection[i].AdapterName);
18             _tprintf(_T("\tDescription : %wS\n\n"), adapters_collection[i].Description);
19         }
20     }
21 
22     return 0;
23 }

运行结果: 

 

 

参考文章

posted on 2021-01-27 17:38  癫狂编程  阅读(280)  评论(0编辑  收藏  举报

导航

好的代码像粥一样,都是用时间熬出来的