Autor Beitrag
Manfred
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 90



BeitragVerfasst: Di 10.05.16 16: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:

ausblenden volle Höhe 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;
// Liefert die MAC-Adressen aller Netzwerkkarten durch Komma getrennt

implementation

FUNCTION GetAdapters: TLanaEnum;
VAR
  NCB        :TNCB;                   //Network Control Block
  LanaEnum   :TLanaEnum;              //Enumeration of Lan Adapters
  ReturnCode :Char;                   //Retun Code

BEGIN
 //Clear NCB Structure
 FillChar(NCB, SizeOf(NCB), 0);
 //Clear LanaEnum Stucture
 FillChar(LanaEnum, SizeOf(TLanaEnum), 0);

 //Programm NBC to ask for the number of Lana's
 NCB.ncb_Command := CHAR(NCBENUM);
 NCB.ncb_buffer  := @LanaEnum;
 NCB.ncb_length  := Sizeof(LanaEnum);

 //Ask NetBios
 ReturnCode := NetBios(@NCB);

 //Check if query was successfull, if returnCode = #0
 IF ReturnCode <> #0 THEN
 BEGIN
  LanaEnum.Length  := CHAR(0);
  LanaEnum.Lana[0] := ReturnCode;
 END;

 // Return valid LanaEnum Structure
 Result := LanaEnum;
END;

FUNCTION GetMacAddress(AdapterID : Integer) : String;
TYPE
 TAdapterStatusA = record
   Adapt : TAdapterStatus;
   NameBuff : array[0..30of TNameBuffer;
 end;
VAR
  NCB           :TNCB;                   //Network Control Block
  ReturnCode    :Char;                   //Retun Code
  AdapterStatus :TAdapterStatus;
BEGIN
 //Clear NCB Structure
 FillChar( NCB, SizeOf(NCB), 0 );

 //Programm NBC to fulfill a reset. It doublecheck if the Lana is present.
 //Can be removed, when used with GetAdapters.
 NCB.ncb_command  := Char(NCBRESET);
 NCB.ncb_lana_num := Char(AdapterID);

 //Process NCB to NetBios
 ReturnCode := NetBios(@NCB);

 //Check if query was successfull, if returnCode = #0
 IF ReturnCode <> #0 THEN
 BEGIN
  // Return the negative returncode
  // Error check would be "if ReturnCode[0]='-' Then..."
  Result:=Char(Ord(ReturnCode)*-1);
  Exit;
 END;

 //Clear NCB Structure
 FillChar( NCB, SizeOf(NCB), 0 );

 //Programm NBC to ask for the MAC associated with the LanaID
 NCB.ncb_command  := Char(NCBASTAT);
 NCB.ncb_lana_num := Char(AdapterID);
 NCB.ncb_buffer   := @AdapterStatus;
 NCB.ncb_length   := SizeOf(AdapterStatus);
 StrCopy(NCB.ncb_callname, '* ' );

 //Process NCB to NetBios
 ReturnCode := Netbios( @NCB );

 //Check if query was successfull, if returnCode = #0
 IF ReturnCode <> #0 THEN
 BEGIN
  // Return the negative returncode
  Result:=Char(Ord(ReturnCode)*-1);
  Exit;
 END;

 //Return formated MAC
 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;                        { enumerate lanas for WIN NT }
  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:

ausblenden volle Höhe 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;
// Liefert die MAC-Adressen aller Netzwerkkarten durch Komma getrennt

implementation

FUNCTION GetAdapters: TLanaEnum;
VAR
  NCB        :TNCB;                   //Network Control Block
  LanaEnum   :TLanaEnum;              //Enumeration of Lan Adapters
  ReturnCode :AnsiChar;                   //Retun Code

BEGIN
 //Clear NCB Structure
 FillChar(NCB, SizeOf(NCB), 0);
 //Clear LanaEnum Stucture
 FillChar(LanaEnum, SizeOf(TLanaEnum), 0);

 //Programm NBC to ask for the number of Lana's
 NCB.ncb_Command := AnsiCHAR(NCBENUM);
 NCB.ncb_buffer  := @LanaEnum;
 NCB.ncb_length  := Sizeof(LanaEnum);

 //Ask NetBios
 ReturnCode := NetBios(@NCB);

 //Check if query was successfull, if returnCode = #0
 IF ReturnCode <> #0 THEN
 BEGIN
  LanaEnum.Length  := AnsiCHAR(0);
  LanaEnum.Lana[0] := ReturnCode;
 END;

 // Return valid LanaEnum Structure
 Result := LanaEnum;
END;

FUNCTION GetMacAddress(AdapterID : Integer) : String;
TYPE
 TAdapterStatusA = record
   Adapt : TAdapterStatus;
   NameBuff : array[0..30of TNameBuffer;
 end;
VAR
  NCB           :TNCB;                   //Network Control Block
  ReturnCode    :AnsiChar;                   //Retun Code
  AdapterStatus :TAdapterStatus;
BEGIN
 //Clear NCB Structure
 FillChar( NCB, SizeOf(NCB), 0 );

 //Programm NBC to fulfill a reset. It doublecheck if the Lana is present.
 //Can be removed, when used with GetAdapters.
 NCB.ncb_command  := AnsiChar(NCBRESET);
 NCB.ncb_lana_num := AnsiChar(AdapterID);

 //Process NCB to NetBios
 ReturnCode := NetBios(@NCB);

 //Check if query was successfull, if returnCode = #0
 IF ReturnCode <> #0 THEN
 BEGIN
  // Return the negative returncode
  // Error check would be "if ReturnCode[0]='-' Then..."
  Result:=AnsiChar(Ord(ReturnCode)*-1);
  Exit;
 END;

 //Clear NCB Structure
 FillChar( NCB, SizeOf(NCB), 0 );

 //Programm NBC to ask for the MAC associated with the LanaID
 NCB.ncb_command  := AnsiChar(NCBASTAT);
 NCB.ncb_lana_num := AnsiChar(AdapterID);
 NCB.ncb_buffer   := @AdapterStatus;
 NCB.ncb_length   := SizeOf(AdapterStatus);
 StrCopy(NCB.ncb_callname, '* ' );

 //Process NCB to NetBios
 ReturnCode := Netbios( @NCB );

 //Check if query was successfull, if returnCode = #0
 IF ReturnCode <> #0 THEN
 BEGIN
  // Return the negative returncode
  Result:=AnsiChar(Ord(ReturnCode)*-1);
  Exit;
 END;

 //Return formated MAC
 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;                        { enumerate lanas for WIN NT }
  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 user profile iconChristian S.: Code- durch Delphi-Tags ersetzt
Moderiert von user profile iconNarses: Titel erweitert.

_________________
Computer können schneller rechnen als wir, deshalb machen sie auch mehr Fehler
baumina
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 305
Erhaltene Danke: 61

Win 7
Delphi 10.2 Tokyo Enterprise
BeitragVerfasst: Di 10.05.16 16:13 
Ist die Unit nb30 ebenfalls umgestellt worden?
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10181
Erhaltene Danke: 1254

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: 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 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 Suche in: Delphi-Forum, Delphi-Library WMI sein, hier dürften sich ebenfalls mit hoher Wahrscheinlichkeit auch in Zukunft funktionsfähig die MAC-Adresse(n) ermitteln lassen. :les:

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Manfred Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 90



BeitragVerfasst: 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

_________________
Computer können schneller rechnen als wir, deshalb machen sie auch mehr Fehler
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10181
Erhaltene Danke: 1254

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 10.05.16 22:35 
Moin!

user profile iconManfred hat folgendes geschrieben Zum zitierten Posting springen:
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

_________________
There are 10 types of people - those who understand binary and those who don´t.
Manfred Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 90



BeitragVerfasst: 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.

_________________
Computer können schneller rechnen als wir, deshalb machen sie auch mehr Fehler
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10181
Erhaltene Danke: 1254

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 11.05.16 10:58 
Moin!

user profile iconManfred hat folgendes geschrieben Zum zitierten Posting springen:
da die Unit "Ping" fehlt.
In dem ARP-MAC-Beitrag war doch ein Link auf den Ping-Thread... :gruebel: :lupe:

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)
ausblenden Quelltext
1:
wmic nic get description,macaddress					

_________________
There are 10 types of people - those who understand binary and those who don´t.
Manfred Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 90



BeitragVerfasst: 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.

_________________
Computer können schneller rechnen als wir, deshalb machen sie auch mehr Fehler