Windows 提供 IPHLPAPI.DLL 中的 GetAdaptersInfo 函式,可擷取本機所有網路介面卡的完整設定資訊,包括 MAC 位址、IP/子網路遮罩、預設閘道、DHCP/WINS 伺服器、租約時間等。本文提供可直接編譯執行的完整原始碼,並說明關鍵結構體與欄位含義。
#include <winsock2.h>
#include <iphlpapi.h>
#include <stdio.h>
#pragma comment(lib, "iphlpapi.lib")
ERROR_BUFFER_OVERFLOW 為預期回傳)。GlobalAlloc(GPTR, size))。PIP_ADAPTER_INFO 連結列表輸出結果。void main(void) {
DWORD dwErr;
PIP_ADAPTER_INFO pAdapterInfo = NULL, pCurr = NULL;
ULONG ulSize = 0;
// 1. 取得所需緩衝區大小
if ((dwErr = GetAdaptersInfo(NULL, &ulSize)) != ERROR_BUFFER_OVERFLOW) {
printf("GetAdaptersInfo sizing failed: %lu\n", dwErr);
return;
}
// 2. 配置記憶體
pAdapterInfo = (PIP_ADAPTER_INFO)GlobalAlloc(GPTR, ulSize);
if (!pAdapterInfo) {
printf("Memory allocation failed\n");
return;
}
// 3. 取得實際介面卡資訊
if ((dwErr = GetAdaptersInfo(pAdapterInfo, &ulSize)) != NO_ERROR) {
printf("GetAdaptersInfo failed: %lu\n", dwErr);
GlobalFree(pAdapterInfo);
return;
}
// 4. 遍歷並輸出每張網卡資訊
for (pCurr = pAdapterInfo; pCurr; pCurr = pCurr->Next) {
// 型別描述
const char* szType = "Other";
switch (pCurr->Type) {
case MIB_IF_TYPE_ETHERNET: szType = "Ethernet"; break;
case MIB_IF_TYPE_TOKENRING: szType = "Token Ring"; break;
case MIB_IF_TYPE_FDDI: szType = "FDDI"; break;
case MIB_IF_TYPE_PPP: szType = "PPP"; break;
case MIB_IF_TYPE_LOOPBACK: szType = "Loopback"; break;
case MIB_IF_TYPE_SLIP: szType = "SLIP"; break;
}
printf("\n%s Adapter %s:\n", szType, pCurr->AdapterName);
printf(" Description : %s\n", pCurr->Description);
// MAC 位址
printf(" Physical Addr: ");
for (UINT i = 0; i < pCurr->AddressLength; ++i) {
printf("%02X%s", pCurr->Address[i], (i == pCurr->AddressLength-1) ? "\n" : "-");
}
printf(" DHCP Enabled : %s\n", pCurr->DhcpEnabled ? "Yes" : "No");
// IP / Subnet / Gateway 列表
PIP_ADDR_STRING pAddr = &pCurr->IpAddressList;
while (pAddr) {
printf(" IP Address : %s\n", pAddr->IpAddress.String);
printf(" Subnet Mask : %s\n", pAddr->IpMask.String);
pAddr = pAddr->Next;
}
pAddr = pCurr->GatewayList.Next;
printf(" Def Gateway : %s\n", pCurr->GatewayList.IpAddress.String);
while (pAddr) {
printf(" %s\n", pAddr->IpAddress.String);
pAddr = pAddr->Next;
}
// DHCP / WINS / 租約時間
printf(" DHCP Server : %s\n", pCurr->DhcpServer.IpAddress.String);
printf(" Primary WINS : %s\n", pCurr->PrimaryWinsServer.IpAddress.String);
printf(" Secondary WINS: %s\n", pCurr->SecondaryWinsServer.IpAddress.String);
time_t tLeaseObtained = pCurr->LeaseObtained;
time_t tLeaseExpires = pCurr->LeaseExpires;
printf(" Lease Obtained: %s", ctime(&tLeaseObtained));
printf(" Lease Expires : %s", ctime(&tLeaseExpires));
}
GlobalFree(pAdapterInfo);
}
IP_ADAPTER_INFO:每張網卡一個節點,透過 Next 形成單向連結列表。IP_ADDR_STRING:IP/遮罩/閘道/DHCP/WINS 皆為此結構,支援多重 IP 設定。LeaseObtained / LeaseExpires:time_t 格式,配合 ctime / gmtime 顯示人類可讀時間。Address 欄位)。GetAdaptersAddresses(支援 IPv6、更完整的旗標),但 GetAdaptersInfo 仍相容保留。GlobalFree 釋放,避免洩漏。iphlpapi.lib,並確保專案設定包含 winsock2.h 在 windows.h 之前(避免衝突)。