Delphi使用WINAPI获取本机所有网卡的Mac信息

做项目有些授权需要网卡硬件信息进行检测,网上可以搜到很多解决方案(copy很多,我也copy一份)。

主要有两种:
1、使用WinSock单元
2、引用Iphlpapi.dll动态库的模式

很多方案都是Char 默认是 AnsiChar的(delphi7)代码,需要修改定义。

测试环境:
1、delphi 2010
2、win7 sp1 x64 (VBox 虚拟机)
3、网卡:桥接 x 2,NAT x 1, 内部地址 x 1 共设置了4个网卡

重点函数

iphlpapi.dll 是windows下一个IP的帮助API功能强大,具体可以到MSDN查看。用C的可以直接引用 IPTYPES.H 单元头,delphi的只能自己定义。

如果出现加载失败等问题,可以查一下DLL是否正常。

function GetAdaptersInfo(AI: PIPAdapterInfo; var BufLen: Integer): Integer;
  stdcall; external 'iphlpapi.dll' Name 'GetAdaptersInfo';

function SendArp(ipaddr: ulong; temp: dword; ulmacaddr: pointer; ulmacaddrleng: pointer): dword;
  stdcall; external 'Iphlpapi.dll' Name 'SendARP';

获取MAC的代码

unit uNetFuncs;

interface

uses
  classes, Windows;

  function GetAdapterInformation(AStrs: TStrings): Integer;
  function GetAdapterInformation2: string;
  function GetLocalMac(var AID: string): integer;


implementation

uses
  SysUtils,
  WinSock;  // inet_addr


const
  MAX_HOSTNAME_LEN = 128; { from IPTYPES.H }
  MAX_DOMAIN_NAME_LEN = 128;
  MAX_SCOPE_ID_LEN = 256;
  MAX_ADAPTER_NAME_LENGTH = 256;
  MAX_ADAPTER_DESCRIPTION_LENGTH = 128;
  MAX_ADAPTER_ADDRESS_LENGTH = 8;

type
  TIPAddressString  = array[0..4 * 4 - 1] of AnsiChar;
  PIPAddrString = ^TIPAddrString;
  TIPAddrString = record
    Next: PIPAddrString;
    IPAddress: TIPAddressString;
    IPMask: TIPAddressString;
    Context: Integer;
  end;
  PFixedInfo = ^TFixedInfo;
  TFixedInfo = record { FIXED_INFO }
    HostName: array[0..MAX_HOSTNAME_LEN + 3] of AnsiChar;
    DomainName: array[0..MAX_DOMAIN_NAME_LEN + 3] of AnsiChar;
    CurrentDNSServer: PIPAddrString;
    DNSServerList: TIPAddrString;
    NodeType: Integer;
    ScopeId: array[0..MAX_SCOPE_ID_LEN + 3] of AnsiChar;
    EnableRouting: Integer;
    EnableProxy: Integer;
    EnableDNS: Integer;
  end;

  PIPAdapterInfo = ^TIPAdapterInfo;
  TIPAdapterInfo = record { IP_ADAPTER_INFO }
    Next: PIPAdapterInfo;
    ComboIndex: Integer;
    AdapterName: array[0..MAX_ADAPTER_NAME_LENGTH + 3] of AnsiChar;
    Description: array[0..MAX_ADAPTER_DESCRIPTION_LENGTH + 3] of AnsiChar;
    AddressLength: Integer;
    Address: array[1..MAX_ADAPTER_ADDRESS_LENGTH] of Byte;
    Index: Integer;
    _Type: Integer;
    DHCPEnabled: Integer;
    CurrentIPAddress: PIPAddrString;
    IPAddressList: TIPAddrString;
    GatewayList: TIPAddrString;
    DHCPServer: TIPAddrString;
    HaveWINS: Bool;
    PrimaryWINSServer: TIPAddrString;
    SecondaryWINSServer: TIPAddrString;
    LeaseObtained: Integer;
    LeaseExpires: Integer;
  end;

function GetAdaptersInfo(AI: PIPAdapterInfo; var BufLen: Integer): Integer;
  stdcall; external 'iphlpapi.dll' Name 'GetAdaptersInfo';

function SendArp(ipaddr: ulong; temp: dword; ulmacaddr: pointer; ulmacaddrleng: pointer): dword;
  stdcall; external 'Iphlpapi.dll' Name 'SendARP';

function GetAdapterInformation(AStrs: TStrings): Integer;
var
  pAI, pWork: PIPAdapterInfo;
  Size: Integer;
  iIdx: Integer;

  function MACToStr(ByteArr: PByte; Len: Integer): string;
  begin
    Result := '';
    while (Len > 0) do begin
      Result := Result + IntToHex(ByteArr^, 2) + '-';
      ByteArr := pointer(Integer(ByteArr) + SizeOf(Byte));
      Dec(Len);
    end;
    SetLength(Result, Length(Result) - 1); { remove last dash }
  end;

  function GetAddrString(Addr: PIPAddrString): string;
  begin
    Result := '';
    while (Addr <> nil) do begin
      Result := Result + 'A: ' + String(Addr^.IPAddress )+ ' M: ' + String(Addr^.IPMask) + #13;
      Addr := Addr^.Next;
    end;
  end;

  function TimeTToDateTimeStr(TimeT: Integer): string;
  const UnixDateDelta = 25569; { days between 12/31/1899 and 1/1/1970 }
  var
    DT: TDateTime;
    TZ: TTimeZoneInformation;
    Res: dword;
  begin
    Result := '';
    if TimeT = 0 then
      Exit;

    { Unix TIME_T is secs since 1/1/1970 }
    DT := UnixDateDelta + (TimeT / (24 * 60 * 60)); { in UTC }
    { calculate bias }
    Res := GetTimeZoneInformation(TZ);
    if (Res = TIME_ZONE_ID_INVALID) then RaiseLastOSError;
    if (Res = TIME_ZONE_ID_STANDARD) then begin
      DT := DT - ((TZ.Bias + TZ.StandardBias) / (24 * 60));
      Result := DateTimeToStr(DT) + ' ' + WideCharToString(TZ.StandardName);
    end
    else begin { daylight saving time }
      DT := DT - ((TZ.Bias + TZ.DaylightBias) / (24 * 60));
      Result := DateTimeToStr(DT) + ' ' + WideCharToString(TZ.DaylightName);
    end;
  end;
begin
  Size := 5120;
  GetMem(pAI, Size);
  try
    if (GetAdaptersInfo(pAI, Size) <> ERROR_SUCCESS) then
      RaiseLastOSError;

    pWork := pAI;
    iIdx := 1;
    repeat
      AStrs.Add('');
      AStrs.Add('Adapter ' + IntToStr(iIdx));
      AStrs.Add(' ComboIndex: ' + IntToStr(pWork^.ComboIndex));
      AStrs.Add(' Adapter name: ' + pWork^.AdapterName);
      AStrs.Add(' Description: ' + pWork^.Description);
      AStrs.Add(' Adapter address: ' + MACToStr(@pWork^.Address, pWork^.AddressLength));
      AStrs.Add(' Index: ' + IntToStr(pWork^.Index));
      AStrs.Add(' Type: ' + IntToStr(pWork^._Type));
      AStrs.Add(' DHCP: ' + IntToStr(pWork^.DHCPEnabled));
      AStrs.Add(' Current IP: ' + GetAddrString(pWork^.CurrentIPAddress));
      AStrs.Add(' IP addresses: ' + GetAddrString(@pWork^.IPAddressList));
      AStrs.Add(' Gateways: ' + GetAddrString(@pWork^.GatewayList));
      AStrs.Add(' DHCP servers: ' + GetAddrString(@pWork^.DHCPServer));
      AStrs.Add(' Has WINS: ' + IntToStr(Integer(pWork^.HaveWINS)));
      AStrs.Add(' Primary WINS: ' + GetAddrString(@pWork^.PrimaryWINSServer));
      AStrs.Add(' Secondary WINS: ' + GetAddrString(@pWork^.SecondaryWINSServer));
      AStrs.Add(' Lease obtained: ' + TimeTToDateTimeStr(pWork^.LeaseObtained));
      AStrs.Add(' Lease expires: ' + TimeTToDateTimeStr(pWork^.LeaseExpires));
      Inc(iIdx);
      pWork := pWork^.Next;
    until (pWork = nil);
  finally
    FreeMem(pAI);
  end;
  Result := iIdx - 1;
end;


function GetAdapterInformation2: string;
var
  pAI, pWork: PIPAdapterInfo;
  iSize: Integer;
  Res: Integer;

  function MACToStr(ByteArr: PByte; Len: Integer): string;
  begin
    Result := '';
    while (Len > 0) do begin
      Result := Result + IntToHex(ByteArr^, 2) + '-';
      ByteArr := pointer(Integer(ByteArr) + SizeOf(Byte));
      Dec(Len);
    end;
    SetLength(Result, Length(Result) - 1); { remove last dash }
  end;
begin
  iSize := 5120;
  GetMem(pAI, iSize);
  try
    Res := GetAdaptersInfo(pAI, iSize);
    if (Res <> ERROR_SUCCESS) then
      RaiseLastOSError;

    pWork := pAI;
    Result := pWork^.Description + '   ' + MACToStr(@pWork^.Address, pWork^.AddressLength);
  finally
    FreeMem(pAI);
  end;
end;

function GetLocalMac(var AID: string): integer;
var
  iLocalIP: ulong;
  rLocalMAC: array[0..5] of Byte;
  iLen: ulong;
begin
  iLocalIP := inet_addr(PAnsiChar('localhost'));
  iLen := Length(rLocalMAC);
  Result := SendArp(iLocalIP, 0, @rLocalMAC, @iLen);
  AID := format('%2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x', [
                     rLocalMAC[0], rLocalMAC[1], rLocalMAC[2],
                     rLocalMAC[3], rLocalMAC[4], rLocalMAC[5]]);
end;


end.

End 蘑菇房