前面有篇文章:《用 WinPcap 获取网络接口列表》,是通过 WinPcap 库来获得网络接口列表,但是拿到的网络接口名称对于人(Human Being)来说毫无意义,如下图:
实际上我们在 Windows 控制面板(Control Panel)中看到的是网络接口的“友好名称”(Friendly Name),如下:
为了拿到网络接口的“友好名称”,我遍查 MSDN,终于找到了答案。以下是我写的程序示例:
NetworkInformation.h
#ifndef _NetworkInformation_H
#define _NetworkInformation_H
#include <vector>
#include <winsock2.h>
#include <iphlpapi.h>
// https://communities.ca.com/thread/241732865
#define MAX_ADAPTER_FriendlyName_LENGTH 65
typedef struct
{
TCHAR AdapterName[MAX_ADAPTER_NAME_LENGTH + 4] = { 0 };
TCHAR Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4] = { 0 };
TCHAR FriendlyName[MAX_ADAPTER_FriendlyName_LENGTH + 4] = { 0 };
GUID NetworkGuid = { 0 };
BYTE PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH] = { 0 };
DWORD PhysicalAddressLength = 0;
union {
ULONG Flags;
struct {
ULONG DdnsEnabled : 1;
ULONG RegisterAdapterSuffix : 1;
ULONG Dhcpv4Enabled : 1;
ULONG ReceiveOnly : 1;
ULONG NoMulticast : 1;
ULONG Ipv6OtherStatefulConfig : 1;
ULONG NetbiosOverTcpipEnabled : 1;
ULONG Ipv4Enabled : 1;
ULONG Ipv6Enabled : 1;
ULONG Ipv6ManagedAddressConfigurationSupported : 1;
};
};
DWORD Mtu = 0;
DWORD IfType = 0;
IF_OPER_STATUS OperStatus = IfOperStatusUnknown;
NET_IF_CONNECTION_TYPE ConnectionType;
TUNNEL_TYPE TunnelType= TUNNEL_TYPE_NONE;
} IP_AdaptersAddresses;
DWORD GetAdaptersAddressesInfo(std::vector<IP_AdaptersAddresses> & adapters_collection);
#endif // _NetworkInformation_H
NetworkInformation.cpp
#include "NetworkInformation.h"
#include <tchar.h>
#include <Windows.h>
#include <winsock2.h>
#include <iphlpapi.h>
#pragma comment(lib, "IPHLPAPI.lib")
#define WORKING_BUFFER_SIZE 81920
DWORD GetAdaptersAddressesInfo(std::vector<IP_AdaptersAddresses> & adapters_collection)
{
DWORD return_code = NO_ERROR;
adapters_collection.clear();
// A pointer to a buffer that contains a linked list of IP_ADAPTER_ADDRESSES structures on successful return.
IP_ADAPTER_ADDRESSES * pAdapterAddresses = nullptr;
IP_ADAPTER_ADDRESSES * pCurrAddresses = nullptr;
// specifies the size of the buffer pointed to by AdapterAddresses.
ULONG sizeOfAdapterAddresses = WORKING_BUFFER_SIZE;
// Return both IPv4 and IPv6 addresses associated with adapters with IPv4 or IPv6 enabled.
ULONG family = AF_UNSPEC;
// Return addresses for all NDIS interfaces.
ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
// This parameter is not currently used, but is reserved for future system use.
PVOID reserved = NULL;
pAdapterAddresses = (IP_ADAPTER_ADDRESSES *)HeapAlloc(GetProcessHeap(), 0, sizeOfAdapterAddresses);
if (pAdapterAddresses == NULL)
{
return_code = 0xFFFFFFFF;
}
memset(pAdapterAddresses, 0, sizeOfAdapterAddresses);
ULONG dwRetVal = GetAdaptersAddresses(family, flags, reserved, pAdapterAddresses, &sizeOfAdapterAddresses);
if (dwRetVal == NO_ERROR)
{
// If successful, output some information from the data we received.
pCurrAddresses = pAdapterAddresses;
while (pCurrAddresses)
{
IP_AdaptersAddresses adapter;
size_t adapter_name_length = strlen(pCurrAddresses->AdapterName);
for (size_t i = 0; i < adapter_name_length; i++)
{
adapter.AdapterName[i] = pCurrAddresses->AdapterName[i];
}
_tcscpy_s(adapter.Description, pCurrAddresses->Description);
_tcscpy_s(adapter.FriendlyName, pCurrAddresses->FriendlyName);
adapter.NetworkGuid = pCurrAddresses->NetworkGuid;
adapter.PhysicalAddressLength = pCurrAddresses->PhysicalAddressLength;
for (size_t i = 0; i < adapter.PhysicalAddressLength; i++)
{
adapter.PhysicalAddress[i] = pCurrAddresses->PhysicalAddress[i];
}
adapter.Flags = pCurrAddresses->Flags;
adapter.Mtu = pCurrAddresses->Mtu;
adapter.IfType = pCurrAddresses->IfType;
adapter.OperStatus = pCurrAddresses->OperStatus;
adapter.ConnectionType = pCurrAddresses->ConnectionType;
adapter.TunnelType = pCurrAddresses->TunnelType;
adapters_collection.push_back(adapter);
pCurrAddresses = pCurrAddresses->Next;
}
}
else
{
switch (dwRetVal)
{
case ERROR_ADDRESS_NOT_ASSOCIATED:
// An address has not yet been associated with the network endpoint.
// DHCP lease information was available.
break;
case ERROR_BUFFER_OVERFLOW:
// The buffer size indicated by the SizePointer parameter is too small to hold the adapter information or
// AdapterAddresses parameter is NULL.
// The SizePointer parameter returned points to the required size of the buffer to hold the adapter information.
break;
case ERROR_INVALID_PARAMETER:
// One of the parameters is invalid. This error is returned for any of the following conditions:
// the SizePointer parameter is NULL, the Address parameter is not AF_INET, AF_INET6, or AF_UNSPEC,
// or the address information for the parameters requested is greater than ULONG_MAX.
break;
case ERROR_NOT_ENOUGH_MEMORY:
// Insufficient memory resources are available to complete the operation.
break;
case ERROR_NO_DATA:
// No addresses were found for the requested parameters.
break;
default:
// Use FormatMessage to obtain the message string for the returned error.
break;
}
return_code = dwRetVal;
}
if (pAdapterAddresses)
{
HeapFree(GetProcessHeap(), 0, pAdapterAddresses);
pAdapterAddresses = nullptr;
}
return return_code;
}
GetNetworkInformation.cpp
// GetNetworkInformation.cpp : Defines the entry point for the console application.
//
#include <io.h>
#include "NetworkInformation.h"
int main()
{
std::vector<IP_AdaptersAddresses> adapters_collection;
DWORD return_code = GetAdaptersAddressesInfo(adapters_collection);
if (return_code == NO_ERROR)
{
size_t count = adapters_collection.size();
for (size_t i = 0; i < count; i++)
{
_tprintf(_T("%d.\tFriendlyName: %wS\n"), i + 1, adapters_collection[i].FriendlyName);
_tprintf(_T("\tAdapterName : %wS\n"), adapters_collection[i].AdapterName);
_tprintf(_T("\tDescription : %wS\n\n"), adapters_collection[i].Description);
}
}
return 0;
}
运行结果: