【转载】获取MAC地址方法大全

From:http://blog.csdn.net/han2814675/article/details/6223617

Windows平台下用C++代码取得机器的MAC地址并不是一件简单直接的事情。到目前为止,作者尚未发现有任何一个通用的100%的适用于所有Windows平台的方法可以稳定的取得MAC地址。而有些应用(比如MMORPG)则需要稳定的得到机器的MAC地址,解决方案往往是通过多种方法依次使用来提高成功率。

说明:

    • 以下方法只会返回多网卡的第一个MAC地址。
    • 网上有很多文章和源码来解决该问题,大多不全或有问题。本篇所有方法均经过整理调试,可直接使用。
    • 作者也不喜欢满篇帖代码,本篇贴代码是方便直接使用,请读者谅解。

下面奉上几种常用的方法:



方法一:通过NetBIOS

[Netbios is not supported on Windows Vista, Windows Server 2008, and subsequent versions of the operating system]

#include <windows.h>

#pragma comment(lib, "Netapi32.lib")

namespace

{

bool GetAdapterInfo(int adapterNum, std::string& macOUT)

{

NCB Ncb;

memset(&Ncb, 0, sizeof(Ncb));

Ncb.ncb_command = NCBRESET; // 重置网卡,以便我们可以查询

Ncb.ncb_lana_num = adapterNum;

if (Netbios(&Ncb) != NRC_GOODRET)

return false;

// 准备取得接口卡的状态块

memset(&Ncb, sizeof(Ncb), 0);

Ncb.ncb_command = NCBASTAT;

Ncb.ncb_lana_num = adapterNum;

strcpy((char *) Ncb.ncb_callname, "*");

struct ASTAT

{

ADAPTER_STATUS adapt;

NAME_BUFFER nameBuff[30];

}adapter;

memset(&adapter,sizeof(adapter), 0);

Ncb.ncb_buffer = (unsigned char *)&adapter;

Ncb.ncb_length = sizeof(adapter);

if (Netbios(&Ncb) != 0)

return false;

char acMAC[32];

sprintf(acMAC, "%02X-%02X-%02X-%02X-%02X-%02X",

int (adapter.adapt.adapter_address[0]),

int (adapter.adapt.adapter_address[1]),

int (adapter.adapt.adapter_address[2]),

int (adapter.adapt.adapter_address[3]),

int (adapter.adapt.adapter_address[4]),

int (adapter.adapt.adapter_address[5]));

macOUT = acMAC;

return true;

}

}

bool GetMacByNetBIOS(std::string& macOUT)

{

// 取得网卡列表

LANA_ENUM adapterList;

NCB Ncb;

memset(&Ncb, 0, sizeof(NCB));

Ncb.ncb_command = NCBENUM;

Ncb.ncb_buffer = (unsigned char *)&adapterList;

Ncb.ncb_length = sizeof(adapterList);

Netbios(&Ncb);

// 取得MAC

for (int i = 0; i < adapterList.length; ++i)

{

if (GetAdapterInfo(adapterList.lana[i], macOUT))

return true;

}

return false;

}

参考:

取得系统中网卡MAC地址的三种方法


方法二:通过对控制台ipconfig /all命令重定向

#include <Windows.h>

#include <boost/regex.hpp>

namespace

{

#if 0

/// @brief 采用字符串查找来提取MAC地址

/// @remark 该方法有很大局限性,并不是所有OS返回的MAC地址前导字符串都是

///     "Physical Address. . . . . . . . . : "

bool ParseMac(const std::string& str, std::string& macOUT)

{

static const std::string beginMarkOfMAC("Physical Address. . . . . . . . . : ");

static const std::string endMarkOfMAC("/r/n");

size_t begin = str.find(beginMarkOfMAC);

if(begin != std::string::npos)

{

begin += beginMarkOfMAC.size();

size_t end = str.find(endMarkOfMAC, begin);

if(end != std::string::npos)

{

macOUT = str.substr(begin, end - begin - 1);

return true;

}

}

return false;

}

#else

/// @brief 采用boost::regex来提取MAC

bool ParseMac(const std::string& str, std::string& macOUT)

{

const static boost::regex expression(

"([0-9a-fA-F]{2})-([0-9a-fA-F]{2})-([0-9a-fA-F]{2})-([0-9a-fA-F]{2})-([0-9a-fA-F]{2})-([0-9a-fA-F]{2})",

boost::regex::perl | boost::regex::icase);

boost::cmatch what;

if(boost::regex_search(str.c_str(), what, expression))

{

macOUT = what[1] + "-" + what[2] + "-" + what[3] + "-" + what[4] + "-" + what[5] + "-" + what[6];

return true;

}

return false;

}

#endif

}

bool GetMacByCmd(std::string& macOUT)

{

bool ret = false;

//初始化返回MAC地址缓冲区

SECURITY_ATTRIBUTES sa;

sa.nLength = sizeof(SECURITY_ATTRIBUTES);

sa.lpSecurityDescriptor = NULL;

sa.bInheritHandle = TRUE;

//创建管道

HANDLE hReadPipe,hWritePipe;

if(CreatePipe(&hReadPipe, &hWritePipe, &sa, 0) == TRUE)

{

//控制命令行窗口信息

STARTUPINFO si;

//返回进程信息

PROCESS_INFORMATION pi;

si.cb = sizeof(STARTUPINFO);

GetStartupInfo(&si);

si.hStdError = hWritePipe;

si.hStdOutput = hWritePipe;

si.wShowWindow = SW_HIDE; //隐藏命令行窗口

si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;

//创建获取命令行进程

if (CreateProcess(NULL, "ipconfig /all", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi) == TRUE)

{

WaitForSingleObject(pi.hProcess, 3000); // 设置超时时间,防止Vista、Win7等操作系统卡死

unsigned long count;

CloseHandle(hWritePipe);

std::string strBuffer(1024 * 10, ‘/0‘); // 准备足够大的缓冲区

if(ReadFile(hReadPipe, const_cast<char*>(strBuffer.data()), strBuffer.size() - 1, &count, 0) == TRUE)

{

strBuffer.resize(strBuffer.find_first_of(‘/0‘)); // 截掉缓冲区后面多余的‘/0‘

ret = ParseMac(strBuffer, macOUT);//提取MAC地址串

}

CloseHandle(pi.hThread);

CloseHandle(pi.hProcess);

}

CloseHandle(hWritePipe); // VS2010下调试,此处会有“An invalid handle was specified”的中断,直接运行正常,原因未知。VS2008上正常。

CloseHandle(hReadPipe);

}

return ret;

}

参考:

Boost编译

VC获取MAC地址的4种方法


方法三:通过SNMP(简单网络访问协议)

#include <snmp.h>

#pragma comment(lib, "snmpapi.lib")

#pragma comment(lib, "Ws2_32.lib")

bool GetMacBySNMP(std::string& macOUT)

{

bool ret = false;

WSADATA WinsockData;

if (WSAStartup(MAKEWORD(2, 0), &WinsockData) != 0)

return false;

// Load the SNMP dll and get the addresses of the functions necessary

const HINSTANCE m_dll = LoadLibrary("inetmib1.dll");

if (m_dll < (HINSTANCE) HINSTANCE_ERROR)

return false;

const PFNSNMPEXTENSIONINIT f_SnmpExtensionInit = (PFNSNMPEXTENSIONINIT) GetProcAddress(m_dll, "SnmpExtensionInit");

const PFNSNMPEXTENSIONINITEX f_SnmpExtensionInitEx = (PFNSNMPEXTENSIONINITEX) GetProcAddress(m_dll, "SnmpExtensionInitEx");

const PFNSNMPEXTENSIONQUERY f_SnmpExtensionQuery = (PFNSNMPEXTENSIONQUERY) GetProcAddress(m_dll, "SnmpExtensionQuery");

const PFNSNMPEXTENSIONTRAP f_SnmpExtensionTrap = (PFNSNMPEXTENSIONTRAP) GetProcAddress(m_dll, "SnmpExtensionTrap");

HANDLE pollForTrapEvent;

AsnObjectIdentifier supportedView;

f_SnmpExtensionInit(GetTickCount(), &pollForTrapEvent, &supportedView);

// Initialize the variable list to be retrieved by f_SnmpExtensionQuery

const AsnObjectIdentifier MIB_NULL = { 0, 0 };

RFC1157VarBind varBind[2];

varBind[0].name = MIB_NULL;

varBind[1].name = MIB_NULL;

RFC1157VarBindList varBindList;

varBindList.list = varBind;

UINT OID_ifEntryType[] = { 1, 3, 6, 1, 2, 1, 2, 2, 1, 3 };

UINT OID_ifEntryNum[] = { 1, 3, 6, 1, 2, 1, 2, 1 };

UINT OID_ipMACEntAddr[] = { 1, 3, 6, 1, 2, 1, 2, 2, 1, 6 };

AsnObjectIdentifier MIB_ifMACEntAddr = { sizeof(OID_ipMACEntAddr) / sizeof(UINT), OID_ipMACEntAddr };

AsnObjectIdentifier MIB_ifEntryType = { sizeof(OID_ifEntryType) / sizeof(UINT), OID_ifEntryType };

AsnObjectIdentifier MIB_ifEntryNum = { sizeof(OID_ifEntryNum) / sizeof(UINT), OID_ifEntryNum };

// Copy in the OID to find the number of entries in the Inteface table

varBindList.len = 1;        // Only retrieving one item

SnmpUtilOidCpy(&varBind[0].name, &MIB_ifEntryNum);

AsnInteger errorStatus;

AsnInteger errorIndex;

f_SnmpExtensionQuery(ASN_RFC1157_GETNEXTREQUEST, &varBindList, &errorStatus, &errorIndex);

varBindList.len = 2;

// Copy in the OID of ifType, the type of interface

SnmpUtilOidCpy(&varBind[0].name, &MIB_ifEntryType);

// Copy in the OID of ifPhysAddress, the address

SnmpUtilOidCpy(&varBind[1].name, &MIB_ifMACEntAddr);

for(int j = 0; j < varBind[0].value.asnValue.number; j++)

{

// Submit the query.  Responses will be loaded into varBindList.

// We can expect this call to succeed a # of times corresponding to the # of adapters reported to be in the system

if(f_SnmpExtensionQuery(ASN_RFC1157_GETNEXTREQUEST, &varBindList, &errorStatus, &errorIndex) == FALSE)

continue;

// Confirm that the proper type has been returned

if(SnmpUtilOidNCmp(&varBind[0].name, &MIB_ifEntryType, MIB_ifEntryType.idLength) != 0)

continue;

// Type 6 describes ethernet interfaces

if(varBind[0].value.asnValue.number != 6)

continue;

// Confirm that we have an address here

if(SnmpUtilOidNCmp(&varBind[1].name, &MIB_ifMACEntAddr, MIB_ifMACEntAddr.idLength) != 0)

continue;

if(varBind[1].value.asnValue.address.stream == NULL)

continue;

// Ignore all dial-up networking adapters

if ((varBind[1].value.asnValue.address.stream[0] == 0x44)

&& (varBind[1].value.asnValue.address.stream[1] == 0x45)

&& (varBind[1].value.asnValue.address.stream[2] == 0x53)

&& (varBind[1].value.asnValue.address.stream[3] == 0x54)

&& (varBind[1].value.asnValue.address.stream[4] == 0x00))

continue;

// Ignore NULL addresses returned by other network interfaces

if ((varBind[1].value.asnValue.address.stream[0] == 0x00)

&& (varBind[1].value.asnValue.address.stream[1] == 0x00)

&& (varBind[1].value.asnValue.address.stream[2] == 0x00)

&& (varBind[1].value.asnValue.address.stream[3] == 0x00)

&& (varBind[1].value.asnValue.address.stream[4] == 0x00)

&& (varBind[1].value.asnValue.address.stream[5] == 0x00))

continue;

char buf[32];

sprintf(buf, "%02X-%02X-%02X-%02X-%02X-%02X",

varBind[1].value.asnValue.address.stream[0],

varBind[1].value.asnValue.address.stream[1],

varBind[1].value.asnValue.address.stream[2],

varBind[1].value.asnValue.address.stream[3],

varBind[1].value.asnValue.address.stream[4],

varBind[1].value.asnValue.address.stream[5]);

macOUT = buf;

ret = true;

break;

}

// Free the bindings

SnmpUtilVarBindFree(&varBind[0]);

SnmpUtilVarBindFree(&varBind[1]);

return ret;

}

参考:

SNMP Provider

SNMP Functions

Install and Enable SNMP Service in Windows XP, Vista and 2003

Visual C++通过snmp获取mac地址


方法四:通过GetAdaptersInfo函数(适用于Windows 2000及以上版本)

#include <winsock2.h>

#include <iphlpapi.h>

#pragma comment(lib, "IPHLPAPI.lib")

bool GetMacByGetAdaptersInfo(std::string& macOUT)

{

bool ret = false;

ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);

PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO*)malloc(sizeof(IP_ADAPTER_INFO));

if(pAdapterInfo == NULL)

return false;

// 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 false;

}

if(GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == NO_ERROR)

{

for(PIP_ADAPTER_INFO pAdapter = pAdapterInfo; pAdapter != NULL; pAdapter = pAdapter->Next)

{

// 确保是以太网

if(pAdapter->Type != MIB_IF_TYPE_ETHERNET)

continue;

// 确保MAC地址的长度为 00-00-00-00-00-00

if(pAdapter->AddressLength != 6)

continue;

char acMAC[32];

sprintf(acMAC, "%02X-%02X-%02X-%02X-%02X-%02X",

int (pAdapter->Address[0]),

int (pAdapter->Address[1]),

int (pAdapter->Address[2]),

int (pAdapter->Address[3]),

int (pAdapter->Address[4]),

int (pAdapter->Address[5]));

macOUT = acMAC;

ret = true;

break;

}

}

free(pAdapterInfo);

return ret;

}

参考:

http://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=13421


方法五:通过GetAdaptersAddresses函数(适用于Windows XP及以上版本)

#include <winsock2.h>

#include <iphlpapi.h>

#pragma comment(lib, "IPHLPAPI.lib")

bool GetMacByGetAdaptersAddresses(std::string& macOUT)

{

bool ret = false;

ULONG outBufLen = sizeof(IP_ADAPTER_ADDRESSES);

PIP_ADAPTER_ADDRESSES pAddresses = (IP_ADAPTER_ADDRESSES*)malloc(outBufLen);

if (pAddresses == NULL)

return false;

// Make an initial call to GetAdaptersAddresses to get the necessary size into the ulOutBufLen variable

if(GetAdaptersAddresses(AF_UNSPEC, 0, NULL, pAddresses, &outBufLen) == ERROR_BUFFER_OVERFLOW)

{

free(pAddresses);

pAddresses = (IP_ADAPTER_ADDRESSES*)malloc(outBufLen);

if (pAddresses == NULL)

return false;

}

if(GetAdaptersAddresses(AF_UNSPEC, 0, NULL, pAddresses, &outBufLen) == NO_ERROR)

{

// If successful, output some information from the data we received

for(PIP_ADAPTER_ADDRESSES pCurrAddresses = pAddresses; pCurrAddresses != NULL; pCurrAddresses = pCurrAddresses->Next)

{

// 确保MAC地址的长度为 00-00-00-00-00-00

if(pCurrAddresses->PhysicalAddressLength != 6)

continue;

char acMAC[32];

sprintf(acMAC, "%02X-%02X-%02X-%02X-%02X-%02X",

int (pCurrAddresses->PhysicalAddress[0]),

int (pCurrAddresses->PhysicalAddress[1]),

int (pCurrAddresses->PhysicalAddress[2]),

int (pCurrAddresses->PhysicalAddress[3]),

int (pCurrAddresses->PhysicalAddress[4]),

int (pCurrAddresses->PhysicalAddress[5]));

macOUT = acMAC;

ret = true;

break;

}

}

free(pAddresses);

return ret;

}

转自http://dearymz.blog.163.com/blog/static/205657420110424426943/

时间: 2024-10-20 08:37:27

【转载】获取MAC地址方法大全的相关文章

android获取mac地址方法

http://www.cnblogs.com/xioapingguo/p/4037513.html 网上找的,记录一下 public static String getMacAdress(){ WifiManager wifi = (WifiManager) sContext.getSystemService(Context.WIFI_SERVICE); WifiInfo info = wifi.getConnectionInfo(); return info.getMacAddress();

Python windows下获取MAC地址的一种方法

我最近有一个项目,使用Python在win32下开发一个COM组建,该COM组建其中一个方法是获取本地电脑的MAC地址. 需求很简单,虽然我是Python新手中的新手,但我还是会使用搜索引擎进行搜索. 百度一下,发现大部分都介绍使用import UUID获取MAC地址,或使用os.popen("ipconfig /all")的方式获取.而后者容易受到操作系统中英文环境影响. 如这篇文章:http://www.cnblogs.com/Jerryshome/archive/2011/11/

C#获取IP及MAC地址 方法

C#获取IP及MAC地址 方法,比较齐全 using System.Net; using System; using System.Management; using System.Runtime.InteropServices; public class getIP { [DllImport("Iphlpapi.dll")] private static extern int SendARP(Int32 dest, Int32 host, ref Int64 mac, ref Int

C#获取MAC地址的几种方法

首先需要用到的一些方法和类: public enum NCBCONST { NCBNAMSZ = 16, MAX_LANA = 254, NCBENUM = 0x37, NRC_GOODRET = 0x00, NCBRESET = 0x32, NCBASTAT = 0x33, NUM_NAMEBUF = 30, } [StructLayout(LayoutKind.Sequential)] public struct ADAPTER_STATUS { [MarshalAs(UnmanagedTy

[记]Linux 获取本机(全部)IP、MAC地址方法 (C/C++)

Linux 获取本机IP.MAC地址用法大全 1 2 //#include <sys/types.h> 3 #include <ifaddrs.h> 4 #include <sys/ioctl.h> 5 #include <net/if.h> 6 #include <string.h> 7 #include <stdio.h> 8 #include <unistd.h> 9 #include <netdb.h>

Android 获取MAC地址最靠谱的方法。

众所周知在安卓开发中,我们经常使用WifiManager获取MAC地址做设备映射,但会出现这样那样的问题,比如说开了WIFI获取不到地址了.不开WIFI获取不到地址了.刚开机获取不到地址了.网卡未启动获取不到地址了.综上所述最靠谱的方法还是直接用busybox读取系统文件中的MAC地址比较稳妥.    public String getMacAddress() {         String result = "";         String Mac = ""

Linux 获取本机IP、MAC地址用法大全

getifaddrs()和struct ifaddrs的使用,获取本机IP ifaddrs结构体定义如下: C代码   struct ifaddrs { struct ifaddrs  *ifa_next;    /* Next item in list */ char            *ifa_name;    /* Name of interface */ unsigned int     ifa_flags;   /* Flags from SIOCGIFFLAGS */ struc

android获取Mac地址和IP地址

获取Mac地址实际项目中测试了如下几种方法:(1)设备开通Wifi连接,获取到网卡的MAC地址(但是不开通wifi,这种方法获取不到Mac地址,这种方法也是网络上使用的最多的方法) //根据Wifi信息获取本地Mac public static String getLocalMacAddressFromWifiInfo(Context context){ WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_

linux win 通用的获取Mac的方法

经测试下面方法获取Mac跨平台 protected override void OnLoad(EventArgs e) { Response.Write(string.Join("<br/>", GetMacString())); Response.Write("<br/>"); base.OnLoad(e); } public NetworkInterface[] NetCardInfo() { return NetworkInterfac