首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

獲取系統網卡 MAC 位址的三種方法:NetBIOS、WMI、IP Helper API

     編輯:VC 教學

前言

MAC 位址是網卡唯一硬體識別碼,常用於軟體授權綁定、資產管理、網路存取控制。Windows 提供多種獲取途徑,本文詳解三種主流方法:**NetBIOS API**(經典、需服務)、**WMI**(腳本友好、資訊豐富)、**IP Helper API**(原生、無相依、高效能)。附完整 C++ 代碼片段。

方法一:NetBIOS API(NCB 命令)

**優點**:速度快、資訊準確。
**缺點**:需啟用 NetBIOS over TCP/IP 服務(檔案共享通常已開啟)。

核心結構:NCB (Network Control Block)


typedef struct _NCB {
    UCHAR ncb_command;      // 命令碼
    UCHAR ncb_retcode;      // 返回碼
    UCHAR ncb_lsn;          // 區段號
    UCHAR ncb_num;          // 編號
    PUCHAR ncb_buffer;      // 資料緩衝區指標
    WORD ncb_length;        // 緩衝區長度
    UCHAR ncb_callname[NCBNAMSZ];
    UCHAR ncb_name[NCBNAMSZ];
    UCHAR ncb_rto;          // 接收逾時
    UCHAR ncb_sto;          // 發送逾時
    void (CALLBACK *ncb_post)(struct _NCB *); // 完成回調
    UCHAR ncb_lana_num;     // LANA 編號
    UCHAR ncb_cmd_cplt;     // 命令完成碼
    UCHAR ncb_reserve[10];  // 保留
    HANDLE ncb_event;       // 事件控制代碼
} NCB, *PNCB;

關鍵命令流程

  1. NCBENUM:列舉系統 LANA(邏輯介面卡編號),緩衝區回傳 LANA_ENUM 結構。
  2. NCBRESET:重置指定 LANA 的網卡,必須先執行才能下達後續命令。
  3. NCBASTAT:查詢介面卡狀態,緩衝區回傳 ADAPTER_STATUS(含 MAC 位址)+ NAME_BUFFER 陣列。

完整步驟


// 1. 列舉 LANA
NCB ncb = {0}; ncb.ncb_command = NCBENUM;
UCHAR lanaEnum[256]; ncb.ncb_buffer = lanaEnum; ncb.ncb_length = 256;
Netbios(&ncb); // 成功後 lanaEnum[0] = 數量, [1..] = LANA 編號

// 2. 遍歷每個 LANA
for (int i=1; i<=lanaEnum[0]; i++) {
    UCHAR lana = lanaEnum[i];
    // 2.1 重置
    NCB rst = {0}; rst.ncb_command = NCBRESET; rst.ncb_lana_num = lana;
    Netbios(&rst);

    // 2.2 查詢狀態
    NCB astat = {0}; astat.ncb_command = NCBASTAT; astat.ncb_lana_num = lana;
    astat.ncb_callname[0] = '*'; // 本機
    ADAPTER_STATUS adapt; NAME_BUFFER names[30];
    astat.ncb_buffer = (UCHAR*)&adapt; astat.ncb_length = sizeof(adapt) + sizeof(names);
    Netbios(&astat);

    // 2.3 取得 MAC (adapt.adapter_address, 6 bytes)
    // 格式化為 "XX:XX:XX:XX:XX:XX"
}

方法二:WMI (Win32_NetworkAdapterConfiguration)

**優點**:程式碼簡潔、支援遠端查詢、可同時獲取 IP、DHCP、DNS 等豐富屬性。
**缺點**:需 WMI 服務、COM 初始化開銷大、執行速度較慢。

C++ (COM) 範例


CoInitializeEx(NULL, COINIT_MULTITHREADED);
IWbemLocator *pLoc; CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (void**)&pLoc);
IWbemServices *pSvc; pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc);
CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);

IEnumWbemClassObject *pEnum;
pSvc->ExecQuery(bstr_t("WQL"), bstr_t("SELECT MACAddress FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled=TRUE"), WBEM_FLAG_FORWARD_ONLY, NULL, &pEnum);

IWbemClassObject *pObj; ULONG uRet;
while (pEnum->Next(WBEM_INFINITE, 1, &pObj, &uRet) == S_OK) {
    VARIANT vt; pObj->Get(L"MACAddress", 0, &vt, 0, 0);
    // vt.bstrVal 即為 "00:11:22:33:44:55" 格式
    VariantClear(&vt); pObj->Release();
}
pEnum->Release(); pSvc->Release(); pLoc->Release(); CoUninitialize();

方法三:IP Helper API (GetAdaptersAddresses)

**優點**:原生 DLL (iphlpapi.dll)、無額外服務相依、效能最佳、支援 IPv6、可獲取完整介面卡資訊(單播/多播/任播位址、閘道、DNS 伺服器)。
**缺點**:結構體較複雜、需動態配置緩衝區。

C++ 範例


#include 
#pragma comment(lib, "iphlpapi.lib")

ULONG bufSize = 15000; // 初始緩衝區
PIP_ADAPTER_ADDRESSES pAddresses = (PIP_ADAPTER_ADDRESSES)malloc(bufSize);
DWORD ret = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &bufSize);
if (ret == ERROR_BUFFER_OVERFLOW) {
    free(pAddresses);
    pAddresses = (PIP_ADAPTER_ADDRESSES)malloc(bufSize);
    ret = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &bufSize);
}
if (ret == NO_ERROR) {
    for (PIP_ADAPTER_ADDRESSES p = pAddresses; p; p = p->Next) {
        if (p->PhysicalAddressLength == 6) { // 乙太網
            // p->PhysicalAddress 指向 6 bytes MAC
            // p->FriendlyName, p->Description, p->OperStatus 等豐富資訊
        }
    }
}
free(pAddresses);

三種方法比較與選擇建議

維度NetBIOSWMIIP Helper API
相依服務NetBIOS over TCP/IPWMI (Winmgmt)無 (核心 DLL)
執行速度快慢 (COM 開銷)最快
程式碼複雜度中 (NCB 結構)高 (COM 模板)中 (結構體巢狀)
資訊豐富度低 (僅 MAC/名稱)極高 (完整網路設定)高 (完整介面卡屬性)
遠端查詢不支援原生支援不支援 (本機)
推薦場景舊系統相容、簡單授權綁定資產管理、庫存掃描、遠端審計高效能本機偵測、安裝程式、授權驗證

總結

  • **現代原生開發首選 IP Helper API**:無相依、高效能、資訊完整。
  • **需遠端或豐富屬性選 WMI**:腳本、管理工具最適合。
  • **維護舊專案或極簡需求用 NetBIOS**:注意服務啟用狀態。
  • 獲取 MAC 後建議**標準化格式化**(大寫、冒號分隔)並**驗證非全零/廣播位址**。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved