admin管理员组文章数量:1532237
2024年1月16日发(作者:)
方法一:通过NetBIOS
[Netbios is not supported on Windows Vista, Windows Server 2008, and
subsequent versions of the operating system]
#include
#pragma comment(lib, "Neta")
namespace
{
bool GetAdapterInfo(int adapterNum, std::string& macOUT)
{
NCB Ncb;
memset(&Ncb, 0, sizeof(Ncb));
_command = NCBRESET; // 重置网卡,以便我们可以查询
_lana_num = adapterNum;
if (Netbios(&Ncb) != NRC_GOODRET)
return false;
// 准备取得接口卡的状态块
memset(&Ncb, sizeof(Ncb), 0);
_command = NCBASTAT;
_lana_num = adapterNum;
strcpy((char *) _callname, "*");
struct ASTAT
{
ADAPTER_STATUS adapt;
NAME_BUFFER nameBuff[30];
}adapter;
memset(&adapter,sizeof(adapter), 0);
_buffer = (unsigned char *)&adapter;
_length = sizeof(adapter);
if (Netbios(&Ncb) != 0)
return false;
char acMAC[32];
sprintf(acMAC, "%02X-%02X-%02X-%02X-%02X-%02X",
int (.adapter_address[0]),
int (.adapter_address[1]),
int (.adapter_address[2]),
int (.adapter_address[3]),
int (.adapter_address[4]),
int (.adapter_address[5]));
macOUT = acMAC;
return true;
}
}
bool GetMacByNetBIOS(std::string& macOUT)
{
// 取得网卡列表 LANA_ENUM adapterList;
NCB Ncb;
memset(&Ncb, 0, sizeof(NCB));
_command = NCBENUM;
N_buffer = (unsigned char *)&adapterList;
_length = sizeof(adapterList);
Netbios(&Ncb);
// 取得MAC
for (int i = 0; i < adapterLis; ++i)
{
if (GetAdapterInfo(adap[i], macOUT))
return true;
}
return false;
}
参考:
取得系统中网卡MAC地址的三种方法
方法二:通过对控制台ipconfig /all命令重定向
#include
#include <>
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("rn");
size_t begin = (beginMarkOfMAC);
if(begin != std::string::npos)
{ begin += beginMark();
size_t end = (endMarkOfMAC, begin);
if(end != std::string::npos)
{
macOUT = st(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;
h = sizeof(SECURITY_ATTRIBUTES);
ecurityDescriptor = NULL;
itHandle = TRUE;
//创建管道
HANDLE hReadPipe,hWritePipe;
if(CreatePipe(&hReadPipe, &hWritePipe, &sa, 0) == TRUE)
{
//控制命令行窗口信息
STARTUPINFO si; //返回进程信息
PROCESS_INFORMATION pi;
= sizeof(STARTUPINFO);
GetStartupInfo(&si);
ror = hWritePipe;
tput = hWritePipe;
sindow = SW_HIDE; //隐藏命令行窗口
Flags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
//创建获取命令行进程
if (CreateProcess(NULL, "ipconfig /all", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi) ==
TRUE)
{ WaitForSingleObject(ss, 3000); // 设置超时时间,防止Vista、Win7等操作系统卡死
unsigned long count;
CloseHandle(hWritePipe);
std::string strBuffer(1024 * 10, '0'); // 准备足够大的缓冲区
if(ReadFile(hReadPipe, const_cast
TRUE)
{
strB(strBuff_first_of('0')); // 截掉缓冲区后面多余的'0'
ret = ParseMac(strBuffer, macOUT);//提取MAC地址串
}
CloseHandle(d);
CloseHandle(ss);
}
CloseHandle(hWritePipe); // VS2010下调试,此处会有“An invalid handle was specified”的中断,直接运行正常,原因未知。VS2008上正常。
CloseHandle(hReadPipe);
}
return ret;
}
参考:
Boost编译
VC获取MAC地址的4种方法
方法三:通过SNMP(简单网络访问协议)
#include
#pragma comment(lib, "sn")
#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("");
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;
v = 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);
varBind = 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.a; 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_ength) !=
0)
continue;
// Type 6 describes ethernet interfaces
if(varBind[0].val != 6)
continue;
// Confirm that we have an address here
if(SnmpUtilOidNCmp(&varBind[1].name, &MIB_ifMACEntAddr,
MIB_ifMAth) != 0)
continue;
if(varBind[1]. == NULL)
continue;
// Ignore all dial-up networking adapters
if ((varBind[1].valus.stream[0] == 0x44)
&& (varBind[1].value.aam[1] == 0x45)
&& (varBind[1].[2] == 0x53)
&& (varBind[1].u[3] == 0x54)
&& (varBind[1].ue.a[4] == 0x00))
continue;
// Ignore NULL addresses returned by other network interfaces
if ((varBind[1].valus.stream[0] == 0x00)
&& (varBind[1].value.aam[1] == 0x00)
&& (varBind[1].[2] == 0x00)
&& (varBind[1].u[3] == 0x00)
&& (varBind[1].ue.a[4] == 0x00)
&& (varBind[1].[5] == 0x00))
continue;
char buf[32];
sprintf(buf, "%02X-%02X-%02X-%02X-%02X-%02X",
varBind[1].ue.[0],
varBind[1].[1],
varBind[1].valus.stream[2],
varBind[1].[3],
varBind[1].ue.[4],
varBind[1].[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
#include
#pragma comment(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:///script/Articles/Vie?aid=13421
方法五:通过GetAdaptersAddresses函数(适用于Windows XP及以上版本)
#include
#include
#pragma comment(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;
}
版权声明:本文标题:获取mac地址的几种方法 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/xitong/1705396602a136844.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论