20
May 08

Delphi: AdapterMacAddress

:: articles :: by Gilberto Saraiva

Camaradas,

Muitos aqui devem ter vivido o problema de obter o endereço MAC de um adaptador de rede wireless, quando o mesmo está desativado.

Eu escrevi uma pequena função que obtem o MAC Address mesmo que o adaptador indicado esteje desativado.
Então vamos lá:

 Delphi |  copy code |? 
01
function AdapterMacAddress(AAdptNum: Cardinal): string;
02
type
03
  PC = PCardinal;
04
  PB = PByte;
05
var
06
  hLib: HMODULE;
07
  { Note: Type from IpHlpApi GetAdaptersInfo(pAdapterInfo: PIP_ADAPTER_INFO;
08
    var pOutBufLen: ULONG): DWORD; stdcall;
09
  }
10
  GetAdptInfo: function(A: Pointer; var B: ULONG): DWORD; stdcall;
11
  i, Size, Buff: Cardinal;
12
begin
13
  Result := '-----';
14
  hLib := LoadLibrary('iphlpapi.dll');
15
  if hLib <> 0 then
16
    try
17
      @GetAdptInfo := GetProcAddress(hLib, 'GetAdaptersInfo');
18
      Size := 0;
19
      if GetAdptInfo(nil, Size) = 111 then
20
      begin
21
        GetMem(Pointer(Buff), Size);
22
        try
23
          if GetAdptInfo(Pointer(Buff), Size) = 0 then
24
            for I := PC(Buff + (640 * AAdptNum) + 400)^ - 1 downto 0 do
25
              Insert(IntToHex(PB(Buff + (640 * AAdptNum) + 404 + I)^, 2),
26
                Result, I + 1);
27
        finally
28
          FreeMem(Pointer(Buff));
29
        end;
30
      end;
31
    finally
32
      FreeLibrary(hLib);
33
    end;
34
end;

Escrevi esse código pra não ter dependências a outras Units, mas como alguns aqui devem saber,
tudo que escrevi é baseado na Biblioteca em anexo, a IpHlpApi.

Para os curiosos vale a pena dar uma olhada nessa Lib.

Agora o mais interessante – Como usar a função acima?
Adicione um TMemo no form(coloquei o name de ‘mmoMACs’).

 Delphi |  copy code |? 
1
  mmoMACs.Lines.Add(AdapterMacAddress(0));
2
  mmoMACs.Lines.Add(AdapterMacAddress(1));

Nesse exemplo eu pego o MAC Address do primeiro e do segundo adaptador.
O retorno aqui ficou:
00-19-DB-9D-D0-4F
00-03-0D-7A-5D-40

Respectivamente, Placa de Rede a Cabo e Placa de Rede Wireless(Desativada no switch do notebook [OFF])

Obs: Lembre-se que em programação iniciamos contagem do 0, então de 0 a 10 temos 11 elementos.

Abraço a todos

Tags: , , ,


7 comments

  1. Olá Gilberto,

    usei essa função e funcionou legal.
    Identifico a máquina do cliente pelo MACADRESS.
    Chamo sempre a função passando o parâmetro zero, que seria para pegar sempre o primeiro.

    Fiz um teste aqui, só com 1 placa de rede onboard.
    Desativei a rede e chamei a função, e me retornou MACADRESS=——

    A função
    GetAdptInfo(nil, Size) está me retornando 232.

    Como posso resolver?
    Estou tendo problema com alguns clientes que ativam o wireless depois depassarmos a licença para ele, provavelmente eles estão desativando a rede normal, e daí meu sistema não valida a licença, pois o macadress muda.

    Aguardo contato.
    Grato pela ajuda até o momento!
    Felipe Teixeira

  2. Camarada,

    Realmente se desativar pelo Gerenciador de dispositivos do Windows, a placa desaparece do Windows. Acho que é caso para uma mudança no código, ou de postura, pois se a desativação da placa altera o sistema de segurança do aplicativo, é muito necessário notificar o cliente da existência desse detalhe importante.

    Outra coisa que você pode fazer é obter mais informações sobre a placa:

    Registro:
    HKEY_LOCAL_MACHINE
    SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces

    Escrevi um função que retorna o GUID da placa de rede no mesmo esquema de utilização:

     Delphi |  copy code |? 
    01
    02
    function AdapterGUID(AAdptNum: Cardinal): string;
    03
    var
    04
      hLib: HMODULE;
    05
      GetAdptInfo: function(A: Pointer; var B: ULONG): DWORD; stdcall;
    06
      i, Size, Buff: Cardinal;
    07
    begin
    08
      hLib := LoadLibrary('iphlpapi.dll');
    09
      if hLib <> 0 then
    10
        try
    11
          @GetAdptInfo := GetProcAddress(hLib, 'GetAdaptersInfo');
    12
          Size := 0;
    13
          if GetAdptInfo(nil, Size) = 111 then
    14
          begin
    15
            GetMem(Pointer(Buff), Size);
    16
            try
    17
              if GetAdptInfo(Pointer(Buff), Size) = 0 then
    18
                for I := 8 to 264 do
    19
                  Result := Result + PChar(Buff + (640 * AAdptNum) + I)^;
    20
            finally
    21
              FreeMem(Pointer(Buff));
    22
            end;
    23
          end;
    24
        finally
    25
          FreeLibrary(hLib);
    26
        end;
    27
    end;
    28

    Veja se consegue mais alguma informação que lhe ajudará na hora de identificar o erro e mudar a inteiração da segurança. Lembre-se que o Registro conserva as informações se as mesma já chegaram a existir, então pode ser uma alternativa.

  3. Opa amigo,

    Esse código realmente é funcional! Mais não estou conseguindo deixar do
    jeito que preciso, será que poderia me ajudar a implementa-lo?
    Estou querendo fazer uma requisição junto ao php para mostrar o mac address em uma determinada página url, Como posso fazer essa requisição na página php contendo

    $mac = $_SERVER['MacAddress'];

    Será que pode me ajudar?

    Muito obrigado
    Até mais

  4. Como seria uma função pra pegar a descrição da placa de rede, algo do tipo: SiS 900 PCI Fast Ethernet Adapter

  5. Já tentou pegar o Mac Address via rede?
    Estou conseguindo, porém no windows 98 não pega o MAC Address de um miro Linux.

    Tem alguma ideia?

  6. Amigo, muito bom seu código! realmente funcional !
    Mas o segundo (pelo registro) está em loop.
    Como resolver isso.
    agradeço!

  7. klayt0on, acho que o código está ok, o loop que existe ali é sequencial e improvável ter deadlock nele, tente ver se alguma exceção está sendo levantada e me comunique se existe, caso contrário acho que pode ser a forma de use que você faz ai.

Leave a comment