Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Portierung Delphi 6 -> Delphi XE (MAC-Adresse ermitteln)
Manfred - Di 10.05.16 16:02
Titel: Portierung Delphi 6 -> Delphi XE (MAC-Adresse ermitteln)
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:
Delphi-Quelltext
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:
Delphi-Quelltext
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.
baumina - Di 10.05.16 16:13
Ist die Unit nb30 ebenfalls umgestellt worden?
Narses - Di 10.05.16 18: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 :zwinker: ... 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 :lupe:). Heute schon nur noch mit hoher (und nicht mehr mit an Sicherheit grenzender) Wahrscheinlichkeit anzutreffen, aber das wird nicht mehr ewig so bleiben. :idea:
Vermutlich ist es besser, man geht
ähnlich wie hier beschrieben [
https://www.entwickler-ecke.de/viewtopic.php?t=94099] 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. :les:
cu
Narses
Manfred - Di 10.05.16 21: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
Narses - Di 10.05.16 22: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. :idea:
Wie gesagt, WMI geht auch. :nixweiss:
cu
Narses
Manfred - Mi 11.05.16 09: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.
Manfred - Mi 11.05.16 14: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.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!