Windows客户端开发--获取系统mac地址(使用GetAdaptersInfo和GetAdaptersAddresses)

使用WMI可以获取本地计算机的mac信息,现在就用另外两种方法获取mac地址:
GetAdaptersInfo 和 GetAdaptersAddresses

GetAdaptersInfo
功能:
The GetAdaptersInfo function retrieves adapter information for the local computer.
原型:

DWORD GetAdaptersInfo(
  _Out_   PIP_ADAPTER_INFO pAdapterInfo,
  _Inout_ PULONG           pOutBufLen
);

其中参数有PIP_ADAPTER_INFO:

typedef struct _IP_ADAPTER_INFO {
    struct _IP_ADAPTER_INFO* Next;
    DWORD ComboIndex;
    char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4];
    char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4];
    UINT AddressLength;
    BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH];
    DWORD Index;
    UINT Type;
    UINT DhcpEnabled;
    PIP_ADDR_STRING CurrentIpAddress;
    IP_ADDR_STRING IpAddressList;
    IP_ADDR_STRING GatewayList;
    IP_ADDR_STRING DhcpServer;
    BOOL HaveWins;
    IP_ADDR_STRING PrimaryWinsServer;
    IP_ADDR_STRING SecondaryWinsServer;
    time_t LeaseObtained;
    time_t LeaseExpires;
} IP_ADAPTER_INFO, *PIP_ADAPTER_INFO;

上面的结构体中,我们注意关注TypeAddressLengthAddress

Type:

#define MIB_IF_TYPE_OTHER               1
#define MIB_IF_TYPE_ETHERNET            6
#define MIB_IF_TYPE_TOKENRING           9
#define MIB_IF_TYPE_FDDI                15
#define MIB_IF_TYPE_PPP                 23
#define MIB_IF_TYPE_LOOPBACK            24
#define MIB_IF_TYPE_SLIP                28

上代码:

bool GetMacAddressByAdaptersInfo(std::string &mac_address)
{
  bool ret = false;

  ULONG out_buf_len = sizeof(IP_ADAPTER_INFO);
  PIP_ADAPTER_INFO adapter_info = (IP_ADAPTER_INFO*)malloc(sizeof(IP_ADAPTER_INFO));
  if (adapter_info == NULL)
    return false;
  // Make an initial call to GetAdaptersInfo to get the necessary size into the out_buf_len variable
  if (GetAdaptersInfo(adapter_info, &out_buf_len) == ERROR_BUFFER_OVERFLOW)
  {
    free(adapter_info);
    adapter_info = (IP_ADAPTER_INFO *)malloc(out_buf_len);
    if (adapter_info == NULL)
      return false;
  }

  if (GetAdaptersInfo(adapter_info, &out_buf_len) == NO_ERROR)
  {
    PIP_ADAPTER_INFO adapter = adapter_info;
    for (; adapter != NULL; adapter = adapter->Next)
    {
      // 确保是以太网
      if (adapter->Type != MIB_IF_TYPE_ETHERNET)
        continue;
      // 确保MAC地址的长度为 00-00-00-00-00-00
      if (adapter->AddressLength != 6)
        continue;

      std::cout << "GetMacAddressByAdaptersInfo: " <<std::hex << int(adapter->Address[0]) <<" "
                << int(adapter->Address[1]) << " "
                << int(adapter->Address[2]) << " "
                << int(adapter->Address[3]) << " "
                << int(adapter->Address[4]) << " "
                << int(adapter->Address[5]) << std::endl;

      ret = true;
      break;
    }
  }

  free(adapter_info);
  return ret;
}

注意:
On Windows XP and later: Use the GetAdaptersAddresses function instead of GetAdaptersInfo.
所以稍后会介绍GetAdaptersAddresses。

GetAdaptersAddresses
功能:
The GetAdaptersAddresses function retrieves the addresses associated with the adapters on the local computer.
原型:
“`cpp
ULONG WINAPI GetAdaptersAddresses(
In ULONG Family,
In ULONG Flags,
In PVOID Reserved,
Inout PIP_ADAPTER_ADDRESSES AdapterAddresses,
Inout PULONG SizePointer
);

第一个参数Family我们设置为AF_UNSPEC:
Return both IPv4 and IPv6 addresses associated with adapters with IPv4 or IPv6 enabled.

其中参数PIP_ADAPTER_ADDRESSES:
```cpp
typedef struct _IP_ADAPTER_ADDRESSES {
  union {
    ULONGLONG Alignment;
    struct {
      ULONG Length;
      DWORD IfIndex;
    };
  };
  struct _IP_ADAPTER_ADDRESSES  *Next;
  PCHAR                              AdapterName;
  PIP_ADAPTER_UNICAST_ADDRESS        FirstUnicastAddress;
  PIP_ADAPTER_ANYCAST_ADDRESS        FirstAnycastAddress;
  PIP_ADAPTER_MULTICAST_ADDRESS      FirstMulticastAddress;
  PIP_ADAPTER_DNS_SERVER_ADDRESS     FirstDnsServerAddress;
  PWCHAR                             DnsSuffix;
  PWCHAR                             Description;
  PWCHAR                             FriendlyName;
  BYTE                               PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH];
  DWORD                              PhysicalAddressLength;
  DWORD                              Flags;
  DWORD                              Mtu;
  DWORD                              IfType;
  IF_OPER_STATUS                     OperStatus;
  DWORD                              Ipv6IfIndex;
  DWORD                              ZoneIndices[16];
  PIP_ADAPTER_PREFIX                 FirstPrefix;
  ULONG64                            TransmitLinkSpeed;
  ULONG64                            ReceiveLinkSpeed;
  PIP_ADAPTER_WINS_SERVER_ADDRESS_LH FirstWinsServerAddress;
  PIP_ADAPTER_GATEWAY_ADDRESS_LH     FirstGatewayAddress;
  ULONG                              Ipv4Metric;
  ULONG                              Ipv6Metric;
  IF_LUID                            Luid;
  SOCKET_ADDRESS                     Dhcpv4Server;
  NET_IF_COMPARTMENT_ID              CompartmentId;
  NET_IF_NETWORK_GUID                NetworkGuid;
  NET_IF_CONNECTION_TYPE             ConnectionType;
  TUNNEL_TYPE                        TunnelType;
  SOCKET_ADDRESS                     Dhcpv6Server;
  BYTE                               Dhcpv6ClientDuid[MAX_DHCPV6_DUID_LENGTH];
  ULONG                              Dhcpv6ClientDuidLength;
  ULONG                              Dhcpv6Iaid;
  PIP_ADAPTER_DNS_SUFFIX             FirstDnsSuffix;
} IP_ADAPTER_ADDRESSES, *PIP_ADAPTER_ADDRESSES;




class="se-preview-section-delimiter">

上面结构体中我们关注:PhysicalAddressLengthPhysicalAddress

上代码:

bool GetMacAddressByAdaptersAddresses(std::string &mac_address)
{
  bool ret = false;

  ULONG out_buf_len = sizeof(IP_ADAPTER_ADDRESSES);
  PIP_ADAPTER_ADDRESSES addresses = (IP_ADAPTER_ADDRESSES*)malloc(out_buf_len);
  if (addresses == NULL)
    return false;
  // Make an initial call to GetAdaptersAddresses to get the necessary size into the ulOutBufLen variable
  if (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, addresses, &out_buf_len) == ERROR_BUFFER_OVERFLOW)
  {
    free(addresses);
    addresses = (IP_ADAPTER_ADDRESSES*)malloc(out_buf_len);
    if (addresses == NULL)
      return false;
  }

  if (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, addresses, &out_buf_len) == NO_ERROR)
  {
    // If successful, output some information from the data we received
    PIP_ADAPTER_ADDRESSES curr_addresses = addresses;
    for (; curr_addresses != NULL; curr_addresses = curr_addresses->Next)
    {
      // 确保MAC地址的长度为 00-00-00-00-00-00
      if (curr_addresses->PhysicalAddressLength != 6)
        continue;

      std::cout << "GetMacAddressByAdaptersAddresses: " << std::hex << int(curr_addresses->PhysicalAddress[0]) << " "
        << int(curr_addresses->PhysicalAddress[1]) << " "
        << int(curr_addresses->PhysicalAddress[2]) << " "
        << int(curr_addresses->PhysicalAddress[3]) << " "
        << int(curr_addresses->PhysicalAddress[4]) << " "
        << int(curr_addresses->PhysicalAddress[5]) << std::endl;

      ret = true;
      break;
    }
  }

  free(addresses);
  return ret;
}

你可能感兴趣的:(windows编程)