[机器码] 获取 MAC 地址的几种方法

本文汇总了多种获取计算机MAC地址的方法,包括使用NetBIOS、设备控制、命令行工具、SNMP、WMI等多种技术手段,并提供了详细的实现代码示例。

Netbios

#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;
}

DeviceIoControl

#include <stdio.h>
#include <locale.h>
#include <tchar.h>

#include <windows.h>
#include <shlwapi.h>
#include <setupapi.h>
#pragma comment(lib, "setupapi.lib")
#include <devguid.h>
#pragma comment(lib, "uuid.lib")
#include <ntddndis.h>
#include <ndisguid.h>
#include <iptypes.h>
#include <regstr.h>

using DIDD_TYPE_BASE = SP_DEVICE_INTERFACE_DETAIL_DATA;
using DIDD_TYPE_CHAR = decltype(*static_cast<DIDD_TYPE_BASE *>(nullptr)->DevicePath);

static constexpr SIZE_T DIDD_SIZE_HEAD = offsetof(DIDD_TYPE_BASE, DevicePath);
static constexpr SIZE_T DIDD_SIZE_BODY = sizeof(DIDD_TYPE_CHAR) * MAX_PATH;
static constexpr SIZE_T DIDD_SIZE_FULL = DIDD_SIZE_HEAD   DIDD_SIZE_BODY;

using DEVICE_INTERFACE_DETAIL_DATA = union DEVICE_INTERFACE_DETAIL_DATA {
   
   
	inline SP_DEVICE_INTERFACE_DETAIL_DATA *operator->() {
   
    return &DetailData; }
	inline SP_DEVICE_INTERFACE_DETAIL_DATA *operator &() {
   
    return &DetailData; }
	SP_DEVICE_INTERFACE_DETAIL_DATA DetailData;
	BYTE Buffer[DIDD_SIZE_FULL];
};

static void SetupDiOutputDeviceAddress(LPCTSTR DevicePath)
{
   
   
	HANDLE hFile = CreateFile(DevicePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
	if (hFile != INVALID_HANDLE_VALUE)
	{
   
   
		BOOL bResult = FALSE;
		BYTE bAddress[MAX_ADAPTER_ADDRESS_LENGTH] = {
   
    0 };
		DWORD dwCtls[] = {
   
    OID_802_3_PERMANENT_ADDRESS, OID_802_3_CURRENT_ADDRESS };
		for (DWORD i = 0; i < ARRAYSIZE(dwCtls); i  )
		{
   
   
			DWORD dwCode = dwCtls[i];
			DWORD cbRead = 0;
			bResult = DeviceIoControl(hFile, IOCTL_NDIS_QUERY_GLOBAL_STATS, &dwCode, sizeof(dwCode), bAddress, sizeof(bAddress), &cbRead, nullptr);
			if (bResult)
			{
   
   
				wprintf(L"网卡地址 [%02X-%02X-%02X-%02X-%02X-%02X]\n", bAddress[0], bAddress[1], bAddress[2], bAddress[3], bAddress[4], bAddress[5]);
				break;
			}
		}

		DWORD dwType = 0;
		DWORD dwCode = OID_GEN_PHYSICAL_MEDIUM;
		DWORD cbRead = 0;
		bResult = DeviceIoControl(hFile, IOCTL_NDIS_QUERY_GLOBAL_STATS, &dwCode, sizeof(dwCode), &dwType, sizeof(dwType), &cbRead, nullptr);
		CloseHandle(hFile);
		if 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值