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

前面有篇文章:《用 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;
}

运行结果:
这里写图片描述

参考文章

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值