在 Delphi 中通过 GetAdaptersInfo 获取有线物理网卡IP、MAC地址
核心思路
完整 Delphi 实现
unit WiredNicHelper;
interface
uses
Windows, SysUtils, WinSock2;
type
// 适配 GetAdaptersInfo 的结构体定义
PIP_ADAPTER_INFO = ^TIP_ADAPTER_INFO;
TIP_ADAPTER_INFO = record
Next: PIP_ADAPTER_INFO;
ComboIndex: DWORD;
AdapterName: array[0..MAX_ADAPTER_NAME_LENGTH + 3] of Char;
Description: array[0..MAX_ADAPTER_DESCRIPTION_LENGTH + 3] of Char;
AddressLength: UINT;
Address: array[0..MAX_ADAPTER_ADDRESS_LENGTH - 1] of Byte;
Index: DWORD;
Type: UINT;
DhcpEnabled: BOOL;
CurrentIpAddress: PIP_ADDR_STRING;
IpAddressList: TIP_ADDR_STRING;
GatewayList: TIP_ADDR_STRING;
DhcpServer: TIP_ADDR_STRING;
HaveWins: BOOL;
PrimaryWinsServer: TIP_ADDR_STRING;
SecondaryWinsServer: TIP_ADDR_STRING;
LeaseObtained: DWORD;
LeaseExpires: DWORD;
end;
const
// 常量定义(匹配 Windows 官方值)
MAX_ADAPTER_NAME_LENGTH = 256;
MAX_ADAPTER_DESCRIPTION_LENGTH = 128;
MAX_ADAPTER_ADDRESS_LENGTH = 8;
MIB_IF_TYPE_ETHERNET = 6; // 有线以太网类型
IF_TYPE_IEEE80211 = 71; // WiFi 无线类型
ERROR_BUFFER_OVERFLOW = 111; // 缓冲区不足错误码
// 声明 GetAdaptersInfo API(来自 iphlpapi.dll)
function GetAdaptersInfo(pAdapterInfo: PIP_ADAPTER_INFO; var pOutBufLen: ULONG): DWORD; stdcall;
external 'iphlpapi.dll' name 'GetAdaptersInfo';
// 核心函数:获取有线物理网卡信息(返回第一个有效网卡的MAC和描述)
function GetPhysicalWiredNic(out MacAddr, NicDesc: string): Boolean;
implementation
// 辅助函数:判断是否为虚拟网卡(过滤虚拟化/虚拟专用网络适配器)
function IsVirtualNic(const Desc: string): Boolean;
const
// 虚拟网卡特征关键词(可根据需要扩展)
VirtualKeywords: array[0..7] of string = (
'VMware', 'VirtualBox', 'Hyper-V', 'VPN', 'TAP-Win32',
'Microsoft Loopback', 'SoftEther', 'WireGuard'
);
var
i: Integer;
begin
Result := False;
for i := Low(VirtualKeywords) to High(VirtualKeywords) do
begin
if Pos(VirtualKeywords[i], Desc) > 0 then
begin
Result := True;
Break;
end;
end;
end;
function GetPhysicalWiredNic(out MacAddr, NicDesc: string): Boolean;
var
pAdapterInfo: PIP_ADAPTER_INFO;
ulOutBufLen: ULONG;
dwRet: DWORD;
pAdapter: PIP_ADAPTER_INFO;
Desc: string;
begin
Result := False;
MacAddr := '';
NicDesc := '';
ulOutBufLen := 0;
pAdapterInfo := nil;
try
// 第一步:调用 GetAdaptersInfo 获取所需缓冲区大小
dwRet := GetAdaptersInfo(nil, ulOutBufLen);
if dwRet <> ERROR_BUFFER_OVERFLOW then
begin
// 无网卡信息或其他错误
Exit;
end;
// 分配缓冲区内存
GetMem(pAdapterInfo, ulOutBufLen);
dwRet := GetAdaptersInfo(pAdapterInfo, ulOutBufLen);
if dwRet <> NO_ERROR then
begin
Exit;
end;
// 第二步:遍历所有网卡,筛选有线物理网卡
pAdapter := pAdapterInfo;
while pAdapter <> nil do
begin
Desc := StrPas(pAdapter^.Description); // 转换为 Delphi 字符串
// 过滤条件1:仅保留以太网类型,排除 WiFi、蓝牙
if (pAdapter^.Type <> MIB_IF_TYPE_ETHERNET) or
(pAdapter^.Type = IF_TYPE_IEEE80211) or
(Pos('Bluetooth', Desc) > 0) then
begin
pAdapter := pAdapter^.Next;
Continue;
end;
// 过滤条件2:排除虚拟网卡
if IsVirtualNic(Desc) then
begin
pAdapter := pAdapter^.Next;
Continue;
end;
// 过滤条件3:MAC地址必须是6字节(物理网卡标准长度)
if pAdapter^.AddressLength <> 6 then
begin
pAdapter := pAdapter^.Next;
Continue;
end;
// 格式化MAC地址(XX:XX:XX:XX:XX:XX)
MacAddr := Format('%.2X:%.2X:%.2X:%.2X:%.2X:%.2X', [
pAdapter^.Address[0], pAdapter^.Address[1], pAdapter^.Address[2],
pAdapter^.Address[3], pAdapter^.Address[4], pAdapter^.Address[5]
]);
NicDesc := Desc;
Result := True;
Break; // 找到第一个符合条件的有线物理网卡即退出
end;
finally
// 释放内存(无论是否成功,都要释放)
if Assigned(pAdapterInfo) then
FreeMem(pAdapterInfo);
end;
end;
end.
使用示例
program GetWiredNicDemo;
uses
Windows, SysUtils, WiredNicHelper;
begin
try
var Mac, Desc: string;
if GetPhysicalWiredNic(Mac, Desc) then
begin
Writeln('找到有线物理网卡:');
Writeln('网卡描述:', Desc);
Writeln('MAC地址:', Mac);
end
else
begin
Writeln('未找到符合条件的有线物理网卡');
end;
except
on E: Exception do
Writeln('错误:', E.Message);
end;
Readln; // 暂停查看结果
end.
关键优化点(解决多网卡筛选问题)
扩展说明
常见问题排查
在 Delphi 中通过 GetAdaptersInfo 获取有线物理网卡IP、MAC地址 https://www.gzza.com/26847.html
本网站资源来自互联网收集,仅供用于学习和交流,请勿用于商业用途。原创内容除特殊说明外,转载本站文章请注明出处。
如有侵权、不妥之处,联系删除。 Email:master@gzza.com
本网站资源来自互联网收集,仅供用于学习和交流,请勿用于商业用途。原创内容除特殊说明外,转载本站文章请注明出处。
如有侵权、不妥之处,联系删除。 Email:master@gzza.com
THE END