from:http://blog.csdn.net/han2814675/article/details/6223617
Using C + + code to get the MAC address of the machine under the Windows platform is not a straightforward matter. So far, the authors have not found any one of the universal 100% methods available for all Windows platforms to obtain a stable MAC address. Some applications (such as MMORPG) need a stable MAC address for the machine, and the solution is often used in several ways to improve the success rate.
Description
-
- The following method returns only the first MAC address of a multi-NIC.
- There are many articles and source code to solve the problem, most of them are not complete or have problems. All methods of this article have been collated and debugged and can be used directly.
- The author also does not like full post code, this post code is convenient to use directly, please the reader understanding.
Here are some common methods:
method One: through NetBIOS
[Netbios isn't supported on Windows Vista, Windows Server, 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; Reset the NIC so we can query Ncb.ncb_lana_num = adapternum;if (Netbios (&NCB)! = Nrc_goodret) return false; // Ready to get the status block of the interface card 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-%0 2x-%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) {//Get NIC list 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); Get macfor (int i = 0; i < adapterlist.length; ++i) {if (Getadapterinfo (Adapterlist.lana[i], macout)) return true;} Retu RN false;}
Reference: Three ways to get the MAC address of the network card in the system
method Two: By redirecting the console Ipconfig/all command
#include <Windows.h> #include <boost/regex.hpp> namespace{#if 0///@brief Use string lookups to extract MAC addresses///@remark This approach has great limitations, not all the MAC address leading strings returned by the OS are/// "Physical Address ...:" bool Parsemac (const std::string& Amp STR, std::string& macout) {static const std::string Beginmarkofmac ("Physical Address ...:"); static cons T 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 use Boost::regex to extract Macbool 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::p erl | 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];re Turn true;} return false;} #endif} bool
Getmacbycmd (std::string& macout) {BOOL RET = false; //initialization returns the MAC address buffer security_attributes sa; sa.nlength = sizeof (security_attributes); Sa.lpsecuritydescriptor = Null; sa.binherithandle = true; //Create pipeline handle hreadpipe,hwritepipe;if ( CreatePipe (&hreadpipe, &hwritepipe, &sa, 0) = = TRUE) {//Control command Line window information Startupinfo si; //return process information Process_ Information PI;SI.CB = sizeof (STARTUPINFO); getstartupinfo (&si); si.hstderror = hWritePipe; Si.hstdoutput = Hwritepipe; si.wshowwindow = Sw_hide; Hide command Line window Si.dwflags = Startf_useshowwindow | startf_usestdhandles; //Create get command line process if (CreateProcess (null, "Ipconfig/all", NULL, NULL, TRUE, 0, NULL, NULL, &SI, &PI) = = TRUE) { waitforsingleobject (pi.hprocess, 3000);//Set time-out to prevent Windows Vista, Win7 and other operating systems from being stuck unsigned long Count CloseHandle (hwritepipe); std::string strbuffer (1024 * 10, '/0 '); Prepare a buffer that is large enough if (ReadFile (Hreadpipe, const_cast<char*> (Strbuffer.data ()), Strbuffer.size ()-1, &count, 0) = = TRUE) {strbuffer.resize (strbuffer.find_first_of ('/0 '));//truncate the buffer behind redundant '/0 ' ret = Parsemac (Strbuffer, macout);// Extract MAC address string}closehandle (Pi.hthread); closehandle (pi.hprocess); }closehandle (hwritepipe); VS2010 under debugging, there will be "an invalid handle is specified" interrupt, direct operation Normal, the reason is unknown. VS2008 on the normal. CloseHandle (hreadpipe);} return ret;}
Reference: Boost compilation VC 4 ways to get MAC address
method Three: Via SNMP (Simple Network Access Protocol)
#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 an D get the addresses of the functions necessaryconst hinstance M_dll = LoadLibrary ("Inetmib1.dll"); if (M_dll < (Hinstanc E) 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 being retrieved by f_sNmpextensionqueryconst 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 Tablevarbindlist.len = 1; //only retrieving one itemsnmputiloidcpy (&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 Interfacesnmputil oidcpy (&varbind[0].name, &mib_ifentrytype); //Copy in the OID of Ifphysaddress, the addresssnmputiloidcpy (&varbind[1].name, &mib_ifmacentaddr); for (int j = 0; J < Varbind[0].value.asnvalue.number; J + +) {// Submit the query. responses'll be loaded into varbindlist.//We can expect this call to succeed a # of times corresponding to the # of adapters reported to being in the SYSTEMIF (F_snmpextensionquery (Asn_rfc1157_getnextrequest, &varbindlist, & ErrorStatus, &errorindex) = = FALSE) continue;//Confirm that the proper type have been Returnedif (SNMPUTILOIDNCMP (& Varbind[0].name, &mib_ifentrytype, mib_ifentrytype.idlength)! = 0) continue;//Type 6 describes Ethernet Interfacesif (Varbind[0].value.asnvalue.number! = 6) continue;//Confirm that we had an address hereif ( 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 Adaptersif ((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 Interfacesif ((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 Bindingssnmputilvarbindfree (&varbind[0]); Snmputilvarbindfree (&varbind[1]); return ret;}
Reference: SNMP providersnmp functionsinstall and Enable snmp Service in Windows XP, Vista and 2003Visual C + + to obtain MAC addresses via SNMP
method Four: Pass the GetAdaptersInfo function (for Windows 2000 and later)
#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 a initial call to GetAdaptersInfo to get the necessary size into the Uloutbuflen Variableif (getadaptersinfo (Padapterinfo, &uloutbuflen) = = Error_buffer_overflow) {free (padapterinfo);p adapterinfo = (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) {//Ensure that the Ethernet IF (padapter->type! = mib_if_type_ethernet) continue;//ensures that the length of the MAC address is 00-00-00-00-00-00if (Padapter->addresslength! = 6) Continue;char acmac[32];sprintf (AcMAC, "%02X-%02X-%02X-%02X-%0 2x-%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;}
Reference: http://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=13421
method Five: Pass the Getadaptersaddresses function (for Windows XP and above)
#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 a initial call to Getadaptersaddresses to get the necessary size into the Uloutbuflen Variableif (getadaptersaddr Esses (af_unspec, 0, NULL, paddresses, &outbuflen) = = Error_buffer_overflow) {free (paddresses);p addresses = (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 receivedfor (pip_adapter_addresses pcurraddresses = paddresses; pcurraddresses! = NULL; PCurrA Ddresses = Pcurraddresses->next) {//Ensure that the length of the MAC address is 00-00-00-00-00-00if (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;} Transfer from http://dearymz.blog.163.com/blog/static/205657420110424426943/
"Reprint" Get MAC Address method Daquan