| 
| Autor | Beitrag |  
| Manfred 
          Beiträge: 90
 
 
 
 
 | 
Verfasst: Di 10.05.16 15:02 
 
Hallo Leidgenossen,
 vor einiger Zeit habe ich unter Delphi 6 eine Routine in diesem Forum gefunden, die mir das Auslesen der MAC-Adresse ermöglicht:
 												| 1:2:
 3:
 4:
 5:
 6:
 7:
 8:
 9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
 20:
 21:
 22:
 23:
 24:
 25:
 26:
 27:
 28:
 29:
 30:
 31:
 32:
 33:
 34:
 35:
 36:
 37:
 38:
 39:
 40:
 41:
 42:
 43:
 44:
 45:
 46:
 47:
 48:
 49:
 50:
 51:
 52:
 53:
 54:
 55:
 56:
 57:
 58:
 59:
 60:
 61:
 62:
 63:
 64:
 65:
 66:
 67:
 68:
 69:
 70:
 71:
 72:
 73:
 74:
 75:
 76:
 77:
 78:
 79:
 80:
 81:
 82:
 83:
 84:
 85:
 86:
 87:
 88:
 89:
 90:
 91:
 92:
 93:
 94:
 95:
 96:
 97:
 98:
 99:
 100:
 101:
 102:
 103:
 104:
 105:
 106:
 107:
 108:
 109:
 110:
 111:
 112:
 113:
 114:
 115:
 116:
 117:
 118:
 119:
 120:
 121:
 
 | unit MyLAN;
 interface
 
 uses SysUtils,nb30;
 
 function MACAddress():string;
 
 implementation
 
 FUNCTION GetAdapters: TLanaEnum;
 VAR
 NCB        :TNCB;                     LanaEnum   :TLanaEnum;                ReturnCode :Char;
 BEGIN
 FillChar(NCB, SizeOf(NCB), 0);
 FillChar(LanaEnum, SizeOf(TLanaEnum), 0);
 
 NCB.ncb_Command := CHAR(NCBENUM);
 NCB.ncb_buffer  := @LanaEnum;
 NCB.ncb_length  := Sizeof(LanaEnum);
 
 ReturnCode := NetBios(@NCB);
 
 IF ReturnCode <> #0 THEN
 BEGIN
 LanaEnum.Length  := CHAR(0);
 LanaEnum.Lana[0] := ReturnCode;
 END;
 
 Result := LanaEnum;
 END;
 
 FUNCTION GetMacAddress(AdapterID : Integer) : String;
 TYPE
 TAdapterStatusA = record
 Adapt : TAdapterStatus;
 NameBuff : array[0..30] of TNameBuffer;
 end;
 VAR
 NCB           :TNCB;                     ReturnCode    :Char;                     AdapterStatus :TAdapterStatus;
 BEGIN
 FillChar( NCB, SizeOf(NCB), 0 );
 
 NCB.ncb_command  := Char(NCBRESET);
 NCB.ncb_lana_num := Char(AdapterID);
 
 ReturnCode := NetBios(@NCB);
 
 IF ReturnCode <> #0 THEN
 BEGIN
 Result:=Char(Ord(ReturnCode)*-1);
 Exit;
 END;
 
 FillChar( NCB, SizeOf(NCB), 0 );
 
 NCB.ncb_command  := Char(NCBASTAT);
 NCB.ncb_lana_num := Char(AdapterID);
 NCB.ncb_buffer   := @AdapterStatus;
 NCB.ncb_length   := SizeOf(AdapterStatus);
 StrCopy(NCB.ncb_callname, '* ' );
 
 ReturnCode := Netbios( @NCB );
 
 IF ReturnCode <> #0 THEN
 BEGIN
 Result:=Char(Ord(ReturnCode)*-1);
 Exit;
 END;
 
 result:=Format('%2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x',
 [ORD(AdapterStatus.Adapter_address[0]),
 ORD(AdapterStatus.Adapter_address[1]),
 ORD(AdapterStatus.Adapter_address[2]),
 ORD(AdapterStatus.Adapter_address[3]),
 ORD(AdapterStatus.Adapter_address[4]),
 ORD(AdapterStatus.Adapter_address[5])])
 end;
 
 function MACAddress():string;
 VAR
 L_Enum :TLanaEnum;
 i,cnt : integer ;
 s : string ;
 BEGIN
 s := '' ;
 L_Enum := GetAdapters;
 cnt := byte(L_Enum.Length) ;
 for i:= 1 to cnt do begin
 s := s + getMACaddress(BYTE(L_Enum.Lana[i-1]));
 if i<cnt then s:=s+',';
 end ;
 result := s;
 end ;
 
 end.
 |  Nun bin ich dabei, diese Routine für XE zu portieren und habe bislang die Char in AnsiChar-Variablen gewandelt:
 												| 1:2:
 3:
 4:
 5:
 6:
 7:
 8:
 9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
 20:
 21:
 22:
 23:
 24:
 25:
 26:
 27:
 28:
 29:
 30:
 31:
 32:
 33:
 34:
 35:
 36:
 37:
 38:
 39:
 40:
 41:
 42:
 43:
 44:
 45:
 46:
 47:
 48:
 49:
 50:
 51:
 52:
 53:
 54:
 55:
 56:
 57:
 58:
 59:
 60:
 61:
 62:
 63:
 64:
 65:
 66:
 67:
 68:
 69:
 70:
 71:
 72:
 73:
 74:
 75:
 76:
 77:
 78:
 79:
 80:
 81:
 82:
 83:
 84:
 85:
 86:
 87:
 88:
 89:
 90:
 91:
 92:
 93:
 94:
 95:
 96:
 97:
 98:
 99:
 100:
 101:
 102:
 103:
 104:
 105:
 106:
 107:
 108:
 109:
 110:
 111:
 112:
 113:
 114:
 115:
 116:
 117:
 118:
 119:
 120:
 121:
 
 | unit MyLAN;
 interface
 
 uses SysUtils,nb30;
 
 function MACAddress():string;
 
 implementation
 
 FUNCTION GetAdapters: TLanaEnum;
 VAR
 NCB        :TNCB;                     LanaEnum   :TLanaEnum;                ReturnCode :AnsiChar;
 BEGIN
 FillChar(NCB, SizeOf(NCB), 0);
 FillChar(LanaEnum, SizeOf(TLanaEnum), 0);
 
 NCB.ncb_Command := AnsiCHAR(NCBENUM);
 NCB.ncb_buffer  := @LanaEnum;
 NCB.ncb_length  := Sizeof(LanaEnum);
 
 ReturnCode := NetBios(@NCB);
 
 IF ReturnCode <> #0 THEN
 BEGIN
 LanaEnum.Length  := AnsiCHAR(0);
 LanaEnum.Lana[0] := ReturnCode;
 END;
 
 Result := LanaEnum;
 END;
 
 FUNCTION GetMacAddress(AdapterID : Integer) : String;
 TYPE
 TAdapterStatusA = record
 Adapt : TAdapterStatus;
 NameBuff : array[0..30] of TNameBuffer;
 end;
 VAR
 NCB           :TNCB;                     ReturnCode    :AnsiChar;                     AdapterStatus :TAdapterStatus;
 BEGIN
 FillChar( NCB, SizeOf(NCB), 0 );
 
 NCB.ncb_command  := AnsiChar(NCBRESET);
 NCB.ncb_lana_num := AnsiChar(AdapterID);
 
 ReturnCode := NetBios(@NCB);
 
 IF ReturnCode <> #0 THEN
 BEGIN
 Result:=AnsiChar(Ord(ReturnCode)*-1);
 Exit;
 END;
 
 FillChar( NCB, SizeOf(NCB), 0 );
 
 NCB.ncb_command  := AnsiChar(NCBASTAT);
 NCB.ncb_lana_num := AnsiChar(AdapterID);
 NCB.ncb_buffer   := @AdapterStatus;
 NCB.ncb_length   := SizeOf(AdapterStatus);
 StrCopy(NCB.ncb_callname, '* ' );
 
 ReturnCode := Netbios( @NCB );
 
 IF ReturnCode <> #0 THEN
 BEGIN
 Result:=AnsiChar(Ord(ReturnCode)*-1);
 Exit;
 END;
 
 result:=Format('%2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x',
 [ORD(AdapterStatus.Adapter_address[0]),
 ORD(AdapterStatus.Adapter_address[1]),
 ORD(AdapterStatus.Adapter_address[2]),
 ORD(AdapterStatus.Adapter_address[3]),
 ORD(AdapterStatus.Adapter_address[4]),
 ORD(AdapterStatus.Adapter_address[5])])
 end;
 
 function MACAddress():string;
 VAR
 L_Enum :TLanaEnum;
 i,cnt : integer ;
 s : string ;
 BEGIN
 s := '' ;
 L_Enum := GetAdapters;
 cnt := byte(L_Enum.Length) ;
 for i:= 1 to cnt do begin
 s := s + getMACaddress(BYTE(L_Enum.Lana[i-1]));
 if i<cnt then s:=s+',';
 end ;
 result := s;
 end ;
 
 end.
 |  Offenbar habe ich aber etwas übersehen.
 Der NetBios-Aufruf in Zeile 30 endet mit dem Errorcode #7
 Ich kenne mich einfach nicht mehr aus, wenn char<>char, word<>word und integer<>integer ist.
 Kann mir jemand auf die Sprünge helfen?
 Danke.
Moderiert von  Christian S.: Code- durch Delphi-Tags ersetzt
Moderiert von  Narses: Titel erweitert._________________ Computer können schneller rechnen als wir, deshalb machen sie auch mehr Fehler
 |  |  |  
| baumina 
          Beiträge: 305
 Erhaltene Danke: 61
 
 Win 7
 Delphi 10.2 Tokyo Enterprise
 
 | 
Verfasst: Di 10.05.16 15:13 
 
Ist die Unit nb30 ebenfalls umgestellt worden? |  |  |  
| Narses 
          
  Beiträge: 10183
 Erhaltene Danke: 1256
 
 W10ent
 TP3 .. D7pro .. D10.2CE
 
 | 
Verfasst: Di 10.05.16 17:36 
 
Moin!
 Ohne jetzt im Detail auf die hier angesprochene Portierungsproblematik einzugehen (leider auch für die gleich folgende Referenz nicht ganz unzutreffend   , sorry, hab nicht viel Zeit): Ich halte es für mittlerweile ... sportlich    ... sich auf die Anwesenheit von NETBIOS-API-Funktionen in modernen Betriebssystemen zu verlassen (diese nb30-Unit wird wohl eine Kapsel für die NETBIOS-API sein, schätze ich mal   ). Heute schon nur noch mit hoher (und nicht mehr mit an Sicherheit grenzender) Wahrscheinlichkeit anzutreffen, aber das wird nicht mehr ewig so bleiben.    Vermutlich ist es besser, man geht ähnlich wie hier beschrieben  vor und holt sich die lokale(n) IP-Adresse(n), die man dann per ARP-API (IPHELPER) in eine MAC-Adresse "übersetzt" (immer dran denken: man kann auch mehr als eine Netzwerkkarte haben, also auch mehr als eine MAC-Adresse!).
 Ein anderer Ansatz könnte auch   WMI  sein, hier dürften sich ebenfalls mit hoher Wahrscheinlichkeit auch in Zukunft funktionsfähig die MAC-Adresse(n) ermitteln lassen.    cu
 Narses_________________ There are 10 types of people - those who understand binary and those who don´t.
 |  |  |  
| Manfred  
          Beiträge: 90
 
 
 
 
 | 
Verfasst: Di 10.05.16 20:17 
 
Danke für die schnelle Antwort.
 nb30 kapselt die netapi32.dll und bietet dafür Konstanten und Types an. Die Versionen für D6 und XE sind nicht identisch, da auch hier Char in AnsiChar etc. gewandelt wurden. Andere Abweichungen habe ich nicht gefunden.
 
 Die API ist jedoch definitiv vorhanden, da die "alte" Version einwandfrei funktioniert. Und das lückenlos von Win XP bis 10 bei 32 und 64 Bit.
 
 Mit der von Narses angebotenen Lösung würde ich gerne liebäugeln, doch es gibt ein Problem: Ich benötige ausschließlich die eigenen MAC-Adressen, nicht alle aus dem Netz.
 
 ---
 
 Nachtrag: Auch die Unit Ping ist unter XE offenbar nicht auffindbar
 _________________ Computer können schneller rechnen als wir, deshalb machen sie auch mehr Fehler
 |  |  |  
| Narses 
          
  Beiträge: 10183
 Erhaltene Danke: 1256
 
 W10ent
 TP3 .. D7pro .. D10.2CE
 
 | 
Verfasst: Di 10.05.16 21:35 
 
Moin!
 	  |  Manfred hat folgendes geschrieben  : |  	  | Ich benötige ausschließlich die eigenen MAC-Adressen, nicht alle aus dem Netz. | 
 Davon war auch nicht die Rede.    Die lokale(n) IP-Adresse(n) ermitteln (also die eigene(n)) und dann über die ARP-API die MAC dazu bestimmen lassen.    Wie gesagt, WMI geht auch.    cu
 Narses_________________ There are 10 types of people - those who understand binary and those who don´t.
 |  |  |  
| Manfred  
          Beiträge: 90
 
 
 
 
 | 
Verfasst: Mi 11.05.16 08:54 
 
Hallo Narses,
 im Prinzip habe ich mit Deiner Unit aber das selbe Problem: Es lässt sich bei mit nicht unter XE compilieren, da die Unit "Ping" fehlt.
 Diese ist offenbar für "GetIPByName" erforderlich.
 _________________ Computer können schneller rechnen als wir, deshalb machen sie auch mehr Fehler
 |  |  |  
| Narses 
          
  Beiträge: 10183
 Erhaltene Danke: 1256
 
 W10ent
 TP3 .. D7pro .. D10.2CE
 
 | 
Verfasst: Mi 11.05.16 09:58 
 
Moin!
 	  |  Manfred hat folgendes geschrieben  : |  	  | da die Unit "Ping" fehlt. | 
 In dem ARP-MAC-Beitrag war doch ein Link auf den Ping-Thread ...      cu
 Narses
 //EDIT: WMI ist auch eine wirklich gute und zuverlässige Quelle für sowas. Gib mal in einer Kommandozeile das hier ein:    (als Demo)
 		                       Quelltext 
 									| 1:
 | wmic nic get description,macaddress					 | _________________ There are 10 types of people - those who understand binary and those who don´t.
 |  |  |  
| Manfred  
          Beiträge: 90
 
 
 
 
 | 
Verfasst: Mi 11.05.16 13:34 
 
Tut mir leid, hatte ich völlig übersehen.
 Danke.
 
 Das mit der Kommandozeile ist in der Tat genau das, was ich suche. Nun muss ich wmic nur noch ins Projekt integrieren.
 _________________ Computer können schneller rechnen als wir, deshalb machen sie auch mehr Fehler
 |  |  |  |