天天看点

c++ windows 获取mac地址

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

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

#include <windows.h> #pragma comment(lib, "Netapi32.lib") namespace { bool GetAdapterInfo(int adapterNum, std::string& macOUT) memset(&Ncb, 0, sizeof(Ncb)); Ncb.ncb_command = NCBRESET; // 重置网卡,以便我们可以查询 Ncb.ncb_lana_num = adapterNum; return false; // 准备取得接口卡的状态块 memset(&Ncb, sizeof(Ncb), 0); Ncb.ncb_command = NCBASTAT; 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); 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); // 取得MAC for (int i = 0; i < adapterList.length; ++i) if (GetAdapterInfo(adapterList.lana[i], macOUT))

参考:

<a href="http://dev.csdn.net/htmls/7/7609.html" target="_blank">取得系统中网卡MAC地址的三种方法</a>

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

#include &lt;Windows.h&gt; #include &lt;boost\regex.hpp&gt; #if 0 /// @brief 采用字符串查找来提取MAC地址 /// @remark 该方法有很大局限性,并不是所有OS返回的MAC地址前导字符串都是 ///     "Physical Address. . . . . . . . . : " bool ParseMac(const std::string&amp; str, std::string&amp; 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); #else 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]; #endif bool GetMacByCmd(std::string&amp; macOUT) bool ret = false; //初始化返回MAC地址缓冲区 SECURITY_ATTRIBUTES sa;  sa.nLength = sizeof(SECURITY_ATTRIBUTES);  sa.lpSecurityDescriptor = NULL;  sa.bInheritHandle = TRUE;  //创建管道 HANDLE hReadPipe,hWritePipe; //控制命令行窗口信息 STARTUPINFO si;  //返回进程信息 PROCESS_INFORMATION pi; si.cb = sizeof(STARTUPINFO);  GetStartupInfo(&amp;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, &amp;si, &amp;pi) == TRUE)  {  WaitForSingleObject(pi.hProcess, 3000); // 设置超时时间,防止Vista、Win7等操作系统卡死 unsigned long count; CloseHandle(hWritePipe); std::string strBuffer(1024 * 10, '\0'); // 准备足够大的缓冲区 if(ReadFile(hReadPipe, const_cast&lt;char*&gt;(strBuffer.data()), strBuffer.size() - 1, &amp;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;

<a href="http://dearymz.blog.163.com/blog/static/20565742009221452985/" target="_blank">Boost编译</a>

<a href="http://blog.csdn.net/pdfmaker/archive/2005/08/26/465748.aspx" target="_blank">VC获取MAC地址的4种方法</a>

#include &lt;snmp.h&gt; #pragma comment(lib, "snmpapi.lib") #pragma comment(lib, "Ws2_32.lib") bool GetMacBySNMP(std::string&amp; macOUT) WSADATA WinsockData; if (WSAStartup(MAKEWORD(2, 0), &amp;WinsockData) != 0)  // Load the SNMP dll and get the addresses of the functions necessary const HINSTANCE m_dll = LoadLibrary("inetmib1.dll"); if (m_dll &lt; (HINSTANCE) HINSTANCE_ERROR) 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(), &amp;pollForTrapEvent, &amp;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(&amp;varBind[0].name, &amp;MIB_ifEntryNum); AsnInteger errorStatus; AsnInteger errorIndex; f_SnmpExtensionQuery(ASN_RFC1157_GETNEXTREQUEST, &amp;varBindList, &amp;errorStatus, &amp;errorIndex); varBindList.len = 2; // Copy in the OID of ifType, the type of interface SnmpUtilOidCpy(&amp;varBind[0].name, &amp;MIB_ifEntryType); // Copy in the OID of ifPhysAddress, the address SnmpUtilOidCpy(&amp;varBind[1].name, &amp;MIB_ifMACEntAddr); for(int j = 0; j &lt; 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, &amp;varBindList, &amp;errorStatus, &amp;errorIndex) == FALSE) continue; // Confirm that the proper type has been returned if(SnmpUtilOidNCmp(&amp;varBind[0].name, &amp;MIB_ifEntryType, MIB_ifEntryType.idLength) != 0) // Type 6 describes ethernet interfaces if(varBind[0].value.asnValue.number != 6)  // Confirm that we have an address here if(SnmpUtilOidNCmp(&amp;varBind[1].name, &amp;MIB_ifMACEntAddr, MIB_ifMACEntAddr.idLength) != 0) if(varBind[1].value.asnValue.address.stream == NULL) // Ignore all dial-up networking adapters if ((varBind[1].value.asnValue.address.stream[0] == 0x44) &amp;&amp; (varBind[1].value.asnValue.address.stream[1] == 0x45) &amp;&amp; (varBind[1].value.asnValue.address.stream[2] == 0x53) &amp;&amp; (varBind[1].value.asnValue.address.stream[3] == 0x54) &amp;&amp; (varBind[1].value.asnValue.address.stream[4] == 0x00))  // Ignore NULL addresses returned by other network interfaces if ((varBind[1].value.asnValue.address.stream[0] == 0x00) &amp;&amp; (varBind[1].value.asnValue.address.stream[1] == 0x00) &amp;&amp; (varBind[1].value.asnValue.address.stream[2] == 0x00) &amp;&amp; (varBind[1].value.asnValue.address.stream[3] == 0x00) &amp;&amp; (varBind[1].value.asnValue.address.stream[4] == 0x00) &amp;&amp; (varBind[1].value.asnValue.address.stream[5] == 0x00))  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(&amp;varBind[0]); SnmpUtilVarBindFree(&amp;varBind[1]);

<a href="http://msdn.microsoft.com/en-us/library/aa393635(VS.85).aspx" target="_blank">SNMP Provider</a>

<a href="http://msdn.microsoft.com/en-us/library/aa378988(v=VS.85).aspx" target="_blank">SNMP Functions</a>

<a href="http://www.mydigitallife.info/2007/11/01/install-and-enable-snmp-service-in-windows-xp-vista-and-2003/" target="_blank">Install and Enable SNMP Service in Windows XP, Vista and 2003</a>

<a href="http://blog.csdn.net/liruda/archive/2008/04/06/2254378.aspx" target="_blank">Visual C++通过snmp获取mac地址</a>

#include &lt;winsock2.h&gt; #include &lt;iphlpapi.h&gt; #pragma comment(lib, "IPHLPAPI.lib") bool GetMacByGetAdaptersInfo(std::string&amp; macOUT) ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO); PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO*)malloc(sizeof(IP_ADAPTER_INFO)); if(pAdapterInfo == NULL) // Make an initial call to GetAdaptersInfo to get the necessary size into the ulOutBufLen variable free(pAdapterInfo); pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen); if (pAdapterInfo == NULL)  for(PIP_ADAPTER_INFO pAdapter = pAdapterInfo; pAdapter != NULL; pAdapter = pAdapter-&gt;Next) // 确保是以太网 if(pAdapter-&gt;Type != MIB_IF_TYPE_ETHERNET) // 确保MAC地址的长度为 00-00-00-00-00-00 if(pAdapter-&gt;AddressLength != 6) int (pAdapter-&gt;Address[0]), int (pAdapter-&gt;Address[1]), int (pAdapter-&gt;Address[2]), int (pAdapter-&gt;Address[3]), int (pAdapter-&gt;Address[4]), int (pAdapter-&gt;Address[5]));

<a href="http://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=13421" target="_blank">http://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=13421</a>

bool GetMacByGetAdaptersAddresses(std::string&amp; macOUT) ULONG outBufLen = sizeof(IP_ADAPTER_ADDRESSES); PIP_ADAPTER_ADDRESSES pAddresses = (IP_ADAPTER_ADDRESSES*)malloc(outBufLen); if (pAddresses == NULL)  // Make an initial call to GetAdaptersAddresses to get the necessary size into the ulOutBufLen variable free(pAddresses); pAddresses = (IP_ADAPTER_ADDRESSES*)malloc(outBufLen); // If successful, output some information from the data we received for(PIP_ADAPTER_ADDRESSES pCurrAddresses = pAddresses; pCurrAddresses != NULL; pCurrAddresses = pCurrAddresses-&gt;Next) if(pCurrAddresses-&gt;PhysicalAddressLength != 6) int (pCurrAddresses-&gt;PhysicalAddress[0]), int (pCurrAddresses-&gt;PhysicalAddress[1]), int (pCurrAddresses-&gt;PhysicalAddress[2]), int (pCurrAddresses-&gt;PhysicalAddress[3]), int (pCurrAddresses-&gt;PhysicalAddress[4]), int (pCurrAddresses-&gt;PhysicalAddress[5])); } 
上一篇: 设计模式
下一篇: 设计模式