直接调用windows的接口获取mac地址,当系统安装了VMWARE 虚拟机,虚拟机创建的网卡的地址也被认为是mac地址。这个时候需要通过注册表将物理mac地址和虚拟mac地址区分出来。
#include <Windows.h>
#include "iphLpapi.h"
#pragma comment(lib, "IPHLPAPI.lib")
std::string getMac() { std::string name; if (!getPhysicalMacName(name)) { return ""; } PIP_ADAPTER_INFO pAdapterInfo; PIP_ADAPTER_INFO pAdapter = NULL; DWORD dwRetVal = 0; ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO); pAdapterInfo = (IP_ADAPTER_INFO *)MALLOC(sizeof(IP_ADAPTER_INFO)); if (pAdapterInfo == NULL) { return ""; } // Make an initial call to GetAdaptersInfo to get // the necessary size into the ulOutBufLen variable if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) { FREE(pAdapterInfo); pAdapterInfo = (IP_ADAPTER_INFO *)MALLOC(ulOutBufLen); if (pAdapterInfo == NULL) { return ""; } } if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) { pAdapter = pAdapterInfo; while (pAdapter) { if (MIB_IF_TYPE_ETHERNET == pAdapter->Type && !name.compare(pAdapter->AdapterName)) { FREE(pAdapterInfo); return byte2UTF8(pAdapter->Address, pAdapter->AddressLength); } pAdapter = pAdapter->Next; } } if (pAdapterInfo) FREE(pAdapterInfo); return ""; } int getPhysicalMacName(std::string& name) { HKEY key; TCHAR szDataBuf[MAX_PATH + 1] = {0}; DWORD dwDataLen = MAX_PATH; DWORD dwType = REG_SZ; HKEY hNetKey = NULL; HKEY hLocalNet = NULL; TCHAR netCfgInstanceIdBuff[512 + 1] = { 0 }; DWORD netCfgInstanceIdlength = 512; DWORD netCfgInstanceId_type = REG_SZ; int index = 0; if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SYSTEM\CurrentControlSet\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318}", 0, KEY_READ, &key)) { return 0; } while (true) { std::wstring sub_key = L"000"; sub_key.append(UTF82WC(std::to_string(index))); if (ERROR_SUCCESS != RegOpenKeyEx(key, sub_key.c_str(), 0, KEY_READ, &hLocalNet)) { RegCloseKey(key); RegCloseKey(hLocalNet); return 0; } memset(szDataBuf, 0, sizeof(szDataBuf[0])); if (ERROR_SUCCESS == RegQueryValueEx(hLocalNet, L"Characteristics", 0, &dwType, (BYTE *)szDataBuf, &dwDataLen)) { if (*((DWORD *)szDataBuf) & 0x4) //0x04是物理网卡 { if (ERROR_SUCCESS == RegQueryValueEx(hLocalNet, L"NetCfgInstanceId", 0, &netCfgInstanceId_type, (BYTE *)netCfgInstanceIdBuff, &netCfgInstanceIdlength)) { name = WC2UTF8(netCfgInstanceIdBuff); RegCloseKey(key); RegCloseKey(hLocalNet); return 1; } } } index++; } RegCloseKey(key); RegCloseKey(hLocalNet); return 0; } std::wstring UTF82WC(const std::string &utf8) { int lenWC = ::MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), static_cast<int>(utf8.length()), NULL, 0); std::unique_ptr<wchar_t> wc(new wchar_t[lenWC]()); ::MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), static_cast<int>(utf8.length()), wc.get(), lenWC); return std::wstring(wc.get(), lenWC); } std::string byte2UTF8(unsigned char* byte_arr, int arr_len) { std::string hexstr; // for (int i = 0; nullptr != byte_arr && i < arr_len; ++i) { char hex1; char hex2; /*借助C++支持的unsigned和int的强制转换,把unsigned char赋值给int的值,那么系统就会自动完成强制转换*/ int value = byte_arr[i]; int S = value / 16; int Y = value % 16; //将C++中unsigned char和int的强制转换得到的商转成字母 if (S >= 0 && S <= 9) { hex1 = (char)(48 + S); } else { hex1 = (char)(55 + S); } //将C++中unsigned char和int的强制转换得到的余数转成字母 if (Y >= 0 && Y <= 9) { hex2 = (char)(48 + Y); } else { hex2 = (char)(55 + Y); } //最后一步的代码实现,将所得到的两个字母连接成字符串达到目的 hexstr = hexstr + hex1 + hex2; } return hexstr; }