如何使用Delphi获取网卡的MAC地址?
Posted
技术标签:
【中文标题】如何使用Delphi获取网卡的MAC地址?【英文标题】:How do I get the MAC address of a network card using Delphi? 【发布时间】:2009-02-23 09:56:13 【问题描述】:如何使用 Delphi 获取网卡的 MacAddress?
【问题讨论】:
【参考方案1】:从Project JEDI API Header Library 获取 Microsoft IP 帮助程序库的 JEDI 转换 - 文件是 IPHlpAPI.zip。解压文件,需要 IpTypes.pas 和 IpHlpApi.pas。然后你可以使用这样的东西:
procedure TForm1.Button1Click(Sender: TObject);
var
NumInterfaces: Cardinal;
AdapterInfo: array of TIpAdapterInfo;
OutBufLen: ULONG;
i: integer;
begin
GetNumberOfInterfaces(NumInterfaces);
SetLength(AdapterInfo, NumInterfaces);
OutBufLen := NumInterfaces * SizeOf(TIpAdapterInfo);
GetAdaptersInfo(@AdapterInfo[0], OutBufLen);
Memo1.Lines.Clear;
for i := 0 to NumInterfaces - 1 do begin
Memo1.Lines.Add(Format('%.2x:%.2x:%.2x:%.2x:%.2x:%.2x',
[AdapterInfo[i].Address[0], AdapterInfo[i].Address[1],
AdapterInfo[i].Address[2], AdapterInfo[i].Address[3],
AdapterInfo[i].Address[4], AdapterInfo[i].Address[5]]));
end;
end;
(所有错误处理都省略了,你当然应该添加它。)
【讨论】:
我用过它,对我来说它把所有的 MAC 地址都设为 00:00:00:00:00:00 。我可能做错了什么?我使用 OutBufLen 作为 Cardinal 而不是这里提到的 ULONG。 @Sanju:没有任何类型的错误检查,因此这可能只是 API 调用失败后的零填充(未初始化)内存。尝试为GetAdaptersInfo()
的结果添加检查。另外,尝试以管理员身份运行它。
IPHlpAPI.zip 不再可用。我在哪里可以找到它?
@Hwau 使用这个网址:github.com/project-jedi/website/tree/master/delphi-jedi.org/www/…【参考方案2】:
GetAdaptersAddresses function 是自 2001 年以来使用 Windows XP 获取适配器信息的首选方式。
适配器的信息在IP_ADAPTER_ADDRESSES structure 中由AdapterAddresses
参数返回。
GetAdaptersAddresses
函数可以检索 IPv4 和 IPv6 地址的信息。调用
GetAdaptersAddresses
函数的推荐方法是预先分配AdapterAddresses
参数指向的15KB工作缓冲区。在典型的计算机上,这大大降低了GetAdaptersAddresses
函数返回ERROR_BUFFER_OVERFLOW
的机会,这需要多次调用GetAdaptersAddresses
函数。
procedure TForm1.Button1Click(Sender: TObject);
const
AF_UNSPEC = 0;
GAA_FLAG_INCLUDE_ALL_INTERFACES = $100;
WORKING_BUFFER_SIZE = 15000;
MAX_TRIES = 3;
var
pAddresses,
pCurrAddresses: PIpAdapterAddresses;
dwRetVal,
outBufLen: Cardinal;
i: Integer;
macAddress: string;
begin
Memo1.Lines.Clear;
outBufLen := WORKING_BUFFER_SIZE;
pAddresses := nil;
i := 0;
repeat
if Assigned(pAddresses) then
FreeMem(pAddresses);
GetMem(pAddresses, outBufLen);
if not Assigned(pAddresses) then
raise Exception.Create('Memory allocation failed for IP_ADAPTER_ADDRESSES struct');
dwRetVal := GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_ALL_INTERFACES, nil, pAddresses, @outBufLen);
Inc(i);
until (dwRetVal <> ERROR_BUFFER_OVERFLOW) or (i = MAX_TRIES);
try
if NO_ERROR <> dwRetVal then begin
if ERROR_NO_DATA = dwRetVal then begin
MessageDlg('No addresses were found for the requested parameters', mtInformation, [mbOK], 0);
Exit;
end
else
raise Exception.Create(SysErrorMessage(dwRetVal));
end;
pCurrAddresses := pAddresses;
while Assigned(pCurrAddresses) do begin
if pCurrAddresses^.PhysicalAddressLength > 0 then begin
Memo1.Lines.Add(pCurrAddresses^.FriendlyName);
macAddress := '';
for i := 0 to pCurrAddresses^.PhysicalAddressLength - 1 do begin
if i > 0 then
macAddress := macAddress + ':';
macAddress := macAddress + Format('%.2X', [pCurrAddresses^.PhysicalAddress[i]]);
end;
Memo1.Lines.Add(macAddress);
Memo1.Lines.Add('');
end;
pCurrAddresses := pCurrAddresses^.Next;
end;
finally
if Assigned(pAddresses) then
FreeMem(pAddresses);
end;
end;
【讨论】:
【参考方案3】:如果你有 Indy,那么你可以使用 MB30(代码取自 https://www.swissdelphicenter.ch/en/showcode.php?id=651)
uses classes, sysUtils, NB30;
function GetMACAdress: TStringList;
var
NCB: PNCB;
Adapter: PAdapterStatus;
URetCode: PChar;
RetCode: char;
I: integer;
Lenum: PlanaEnum;
_SystemID: string;
TMPSTR: string;
begin
Result := TStringList.create();
_SystemID := '';
Getmem(NCB, SizeOf(TNCB));
Fillchar(NCB^, SizeOf(TNCB), 0);
Getmem(Lenum, SizeOf(TLanaEnum));
Fillchar(Lenum^, SizeOf(TLanaEnum), 0);
Getmem(Adapter, SizeOf(TAdapterStatus));
Fillchar(Adapter^, SizeOf(TAdapterStatus), 0);
Lenum.Length := chr(0);
NCB.ncb_command := chr(NCBENUM);
NCB.ncb_buffer := Pointer(Lenum);
NCB.ncb_length := SizeOf(Lenum);
RetCode := Netbios(NCB);
try
i := 0;
repeat
Fillchar(NCB^, SizeOf(TNCB), 0);
Ncb.ncb_command := chr(NCBRESET);
Ncb.ncb_lana_num := lenum.lana[I];
RetCode := Netbios(Ncb);
Fillchar(NCB^, SizeOf(TNCB), 0);
Ncb.ncb_command := chr(NCBASTAT);
Ncb.ncb_lana_num := lenum.lana[I];
// Must be 16
Ncb.ncb_callname := '* ';
Ncb.ncb_buffer := Pointer(Adapter);
Ncb.ncb_length := SizeOf(TAdapterStatus);
RetCode := Netbios(Ncb);
//---- calc _systemId from mac-address[2-5] XOR mac-address[1]...
if (RetCode = chr(0)) or (RetCode = chr(6)) then
begin
_SystemId := IntToHex(Ord(Adapter.adapter_address[0]), 2) + '-' +
IntToHex(Ord(Adapter.adapter_address[1]), 2) + '-' +
IntToHex(Ord(Adapter.adapter_address[2]), 2) + '-' +
IntToHex(Ord(Adapter.adapter_address[3]), 2) + '-' +
IntToHex(Ord(Adapter.adapter_address[4]), 2) + '-' +
IntToHex(Ord(Adapter.adapter_address[5]), 2);
if (_SystemID <> '00-00-00-00-00-00') and (Result.IndexOf(_SystemID)=-1) then
Result.add(_SystemId);
end;
Inc(i);
until (I >= Ord(Lenum.Length));
finally
FreeMem(NCB);
FreeMem(Adapter);
FreeMem(Lenum);
end;
end;
【讨论】:
【参考方案4】:几乎不了解 delphi,如何运行 %system32%\ipconfig.exe /all 并解析输出?
【讨论】:
输出可能是本地化的,因此解析需要针对不同版本的 Windows 进行测试 - 从阿富汗到津巴布韦 最糟糕的方法,除了本地化之外,Windows 版本之间的输出可能会发生变化、添加 IPv6、额外的网卡并且没有错误处理。以上是关于如何使用Delphi获取网卡的MAC地址?的主要内容,如果未能解决你的问题,请参考以下文章