Board index » delphi » need to grab card MAC address

need to grab card MAC address

It may be already in one of my tools, but, doggone it, it may not... is
there a way in Delphi to Get_MAC_address, the eight byte string that is
hard coded in the ethernet card?
If it is too obvious, I will be embarrassed, but I will also have it,
and can move on to other more wonderous things. Thanks!
 

Re:need to grab card MAC address


Quote
Charles Walter wrote:
> It may be already in one of my tools, but, doggone it, it may not... is
> there a way in Delphi to Get_MAC_address, the eight byte string that is
> hard coded in the ethernet card?
> If it is too obvious, I will be embarrassed, but I will also have it,
> and can move on to other more wonderous things. Thanks!

it rurns out to be rather hard to get.

you can get it from netbios. Sometimes.
you used to be able to get it from a GUID but you can't now

one issue is that if you have multiple cards,
which NIC?

the most reliable way to get it is to run
ipconfig and read the results

Grahame

Re:need to grab card MAC address


        Thanks for your response, but I have seen applications that report the
MAC address, while the user is doing some sort of configuration job. In
fact, ipconfig is a <utility> application.
        If there is more than one card, I would read them all, like ipconfig would.
        Maybe I need to do something at a lower level...  like importing a
(possibly Delphi-unsupported) winAPI function and then calling it. Any
suggestion here?
        The MAC address should be readable within Delphi some way... maybe you
have to send an inquiry to a daemon sitting at a TCP port, I am only
guessing. I would hate to re-invent an already known wheel.
        Charles
Quote
> it rurns out to be rather hard to get.

> you can get it from netbios. Sometimes.
> you used to be able to get it from a GUID but you can't now

> one issue is that if you have multiple cards,
> which NIC?

> the most reliable way to get it is to run
> ipconfig and read the results

> Grahame

Re:need to grab card MAC address


Look up the GetAdaptersInfo function.

Not supported on all OSes.

Kelly

Quote
"Charles Walter" <char...@litek.com> wrote in message

news:3ecee411@newsgroups.borland.com...
Quote
> Thanks for your response, but I have seen applications that report the
> MAC address, while the user is doing some sort of configuration job. In
> fact, ipconfig is a <utility> application.
> If there is more than one card, I would read them all, like ipconfig
would.
> Maybe I need to do something at a lower level...  like importing a
> (possibly Delphi-unsupported) winAPI function and then calling it. Any
> suggestion here?
> The MAC address should be readable within Delphi some way... maybe you
> have to send an inquiry to a daemon sitting at a TCP port, I am only
> guessing. I would hate to re-invent an already known wheel.
> Charles

> > it rurns out to be rather hard to get.

> > you can get it from netbios. Sometimes.
> > you used to be able to get it from a GUID but you can't now

> > one issue is that if you have multiple cards,
> > which NIC?

> > the most reliable way to get it is to run
> > ipconfig and read the results

> > Grahame

Re:need to grab card MAC address


Oh...

GetIfEntry is supported on more OSes (NT 4.0 included).

Kelly

Quote
"Charles Walter" <char...@litek.com> wrote in message

news:3ecee411@newsgroups.borland.com...
Quote
> Thanks for your response, but I have seen applications that report the
> MAC address, while the user is doing some sort of configuration job. In
> fact, ipconfig is a <utility> application.
> If there is more than one card, I would read them all, like ipconfig
would.
> Maybe I need to do something at a lower level...  like importing a
> (possibly Delphi-unsupported) winAPI function and then calling it. Any
> suggestion here?
> The MAC address should be readable within Delphi some way... maybe you
> have to send an inquiry to a daemon sitting at a TCP port, I am only
> guessing. I would hate to re-invent an already known wheel.
> Charles

> > it rurns out to be rather hard to get.

> > you can get it from netbios. Sometimes.
> > you used to be able to get it from a GUID but you can't now

> > one issue is that if you have multiple cards,
> > which NIC?

> > the most reliable way to get it is to run
> > ipconfig and read the results

> > Grahame

Re:need to grab card MAC address


Hello Charles,
This is from Torry's Delphi pages under tips and tricks.
Good Luck

uses NB30;

function GetMACAdress: string;
var
  NCB: PNCB;
  Adapter: PAdapterStatus;

  URetCode: PChar;
  RetCode: char;
  I: integer;
  Lenum: PlanaEnum;
  _SystemID: string;
  TMPSTR: string;
begin
  Result    := '';
  _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);

  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);
    end;
    Inc(i);
  until (I >= Ord(Lenum.Length)) or (_SystemID <> '00-00-00-00-00-00');
  FreeMem(NCB);
  FreeMem(Adapter);
  FreeMem(Lenum);
  GetMacAdress := _SystemID;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  label1.Caption := GetMACAdress;

Quote
"Charles Walter" <char...@litek.com> wrote in message

news:3ecec226@newsgroups.borland.com...
Quote
> It may be already in one of my tools, but, doggone it, it may not... is
> there a way in Delphi to Get_MAC_address, the eight byte string that is
> hard coded in the ethernet card?
> If it is too obvious, I will be embarrassed, but I will also have it,
> and can move on to other more wonderous things. Thanks!

Re:need to grab card MAC address


Bob,
I dropped your code in place, and..... IT WORKS !
Oh, thank you thank you, news groups rock. I will pop up somewhere to
help another, you'll see.
Charles

Re:need to grab card MAC address


Quote
Charles Walter wrote:
> Bob,
> I dropped your code in place, and..... IT WORKS !

warning: this is the netbios call, and it doesn't
always work - depends how the PC is set up.

The getIfEntry/getAdaptorsInfo approach is more
reliable if it's supported. (Yay microsoft)

Grahame

Re:need to grab card MAC address


Quote
"Grahame Grieve" <grah...@kestral.com.au> wrote in message

news:rdg8q-ic7.ln1@melblink.kestral.com.au...

Quote
> warning: this is the netbios call, and it doesn't
> always work - depends how the PC is set up.

> The getIfEntry/getAdaptorsInfo approach is more
> reliable if it's supported. (Yay microsoft)

There is another method using SNMP.
(ftp://delphi-jedi.org/api/snmp.zip)

procedure GetMACAddresses(List: TStrings);
const
  InetMib1 = 'inetmib1.dll';
  DunAdapterAddress: array[0..4] of Byte = ($44, $45, $53, $54, $00);
  NullAdapterAddress: array[0..5] of Byte = ($00, $00, $00, $00, $00, $00);
  OID_ipMACEntAddr: array[0..9] of UINT = (1, 3, 6, 1, 2, 1, 2, 2, 1, 6);
  OID_ifEntryType: array [0..9] of UINT = (1, 3, 6, 1, 2, 1, 2, 2, 1, 3);
  OID_ifEntryNum: array [0..7] of UINT = (1, 3, 6, 1, 2, 1, 2, 1);
var
  PollForTrapEvent: THandle;
  SupportedView: PAsnObjectIdentifier;
  MIB_ifMACEntAddr: TAsnObjectIdentifier;
  MIB_ifEntryType: TAsnObjectIdentifier;
  MIB_ifEntryNum: TAsnObjectIdentifier;
  varBindList: TSnmpVarBindList;
  varBind: array[0..1] of TSnmpVarBind;
  ErrorStatus, ErrorIndex: TAsnInteger;
  Dtmp, I: Integer;
  Ret: Boolean;
  MAC: PByteArray;
begin
  if not LoadSnmpExtension(InetMib1) then
    RaiseLastWin32Error;

  MIB_ifMACEntAddr.idLength := Length(OID_ipMACEntAddr);
  MIB_ifMACEntAddr.ids := @OID_ipMACEntAddr;
  MIB_ifEntryType.idLength := Length(OID_ifEntryType);
  MIB_ifEntryType.ids := @OID_ifEntryType;
  MIB_ifEntryNum.idLength := Length(OID_ifEntryNum);
  MIB_ifEntryNum.ids := @OID_ifEntryNum;

  if not SnmpExtensionInit(GetTickCount, PollForTrapEvent, SupportedView)
then
    raise Exception.Create('SnmpExtensionInit failed');

  // Initialize the variable list to be retrieved by m_Query
  varBindList.list := @varBind[0];
  varBind[0].name := DEFINE_NULLOID;
  varBind[1].name := DEFINE_NULLOID;

  // Copy in the OID to find the number of entries in the Inteface table
  varBindList.len := 1;        // Only retrieving one item
  SnmpUtilOidCpy(@varBind[0].name, @MIB_ifEntryNum);

  Ret := SnmpExtensionQuery(SNMP_PDU_GETNEXT, varBindList, ErrorStatus,
ErrorIndex);

  List.Add(Format('Number of adapters: %d', [varBind[0].value.number]));

  varBindList.len := 2;

  // Copy in the OID of ifType, the type of interface
  SnmpUtilOidCpy(@varBind[0].name, @MIB_ifEntryType);

  // Copy in the OID of ifPhysAddress, the address
  SnmpUtilOidCpy(@varBind[1].name, @MIB_ifMACEntAddr);

  I := 0;
  while Ret do
  begin
    // Submit the query.  Responses will be loaded into varBindList.
    // We can expect this call to succeed a # of times corresponding
    // to the # of adapters reported to be in the system
    Ret := SnmpExtensionQuery(SNMP_PDU_GETNEXT, varBindList, ErrorStatus,
ErrorIndex);
    if Ret then
    begin
      // Confirm that the proper type has been returned
      Ret := SnmpUtilOidNCmp(@varBind[0].name, @MIB_ifEntryType,
MIB_ifEntryType.idLength) = SNMP_ERRORSTATUS_NOERROR;
      if Ret then
      begin
        Inc(I);
        Dtmp := varBind[0].value.number;
        List.Add(Format('Interface #%d type: %d', [I, Dtmp]));
        // Type 6 describes ethernet interfaces
        if Dtmp = 6 then
        begin
          // Confirm that we have an address here
          Ret := SnmpUtilOidNCmp(@varBind[1].name, @MIB_ifMACEntAddr,
MIB_ifMACEntAddr.idLength) = SNMP_ERRORSTATUS_NOERROR;
          if Ret and (varBind[1].value.address.stream <> nil) then
          begin
            MAC := PByteArray(varBind[1].value.address.stream);
            if CompareMem(MAC, @DunAdapterAddress,
SizeOf(DunAdapterAddress)) then
              List.Add('DUN adapter')
            else
            if CompareMem(MAC, @NullAdapterAddress,
SizeOf(NullAdapterAddress)) then
              List.Add('NULL adapter')
            else
              List.Add(Format('MAC Address of interface #%d:
%.2x-%.2x-%.2x-%.2x-%.2x-%.2x', [I, MAC[0], MAC[1], MAC[2], MAC[3], MAC[4],
MAC[5]]));
          end;
        end;
      end;
    end;
  end;

  UnloadSnmpExtension;

  SnmpUtilVarBindFree(@varBind[0]);
  SnmpUtilVarBindFree(@varBind[1]);
end;

Re:need to grab card MAC address


I tried both suggestions submitted here, and they both work on "MY"
machine. I am gratefull for you guys' feadback.

Other Threads