Hi Hannes,
>I am a schoolteacher learning Delphi. I want to try your code as a unit2 used by Unit1 with a button and label on the form that has the code
First of all, I'd like to thank narayana for posting some very nice code for finding MAC addresses. This has never been an easy or particularly straightforward task.
One of the first things to understand is that the MAC address is a property of the Ethernet controller on a motherboard or NIC card. Without such a device, a computer won't have a MAC address at all. And, to complicate things, it's not uncommon, now, to find machines with multiple NIC cards and, therefore multiple NIC addresses.
>I am a schoolteacher learning Delphi. I want to try your code as a unit2 used by Unit1 with a button and label on the form that has the code
> Label1.Caption := //What must go here to display the MAC Address (or should it be a ListBox because you seem to determine more than one MAC address)?
You're right in thinking you'll want a way to display more than one MAC address. More about that in a moment.
>Your code is way above me, as I have never (yet) used pointers.
Just a quick comment on that. In Delphi, almost everything is already a pointer, so you rarely encounter the need to use pointers directly. Don't be troubled that narayana's code uses a pointer because your code doesn't really have to "know" anything about it. His function, complex as it is, returns a TStringList, one of the most common (and useful) constructs in Delphi. When using his code, you'll only have to deal with the TStringList he returns.
>I have also only used classes (records a long time ago with Pascal). I'm using D7 and run XP, Win7 32-bit and Win7 64-bit. I have a solution using NB30 but it only works on Win7 64-bit, even if I enable NetBIOS on the other OSs (gives error $30).
Caveat: I haven't tested narayana's' code, but it looks reasonable.
For a start, try this:
* You can put his code in its own unit if you like - or simply put it into you own unit's code.
* In your code, do something like this: var myStringList : TStringList; begin // Note: You don't need to consturct the StringList - the function below does that. myStringList := Get_EthernetAddresses; if myStringList.Count > 0 then Label1.Caption := myStringList.Strings[0] else Label1.Caption := 'No MAC addresses found.'; myStringList.Free; end;
Three comments about the above:
First you're checking to be sure Get_EthernetAddresses returned anything besides an empty StringList.
Second, only if there are more than zero strings (MAC Addresses) in the StringList, do you assign one (the first one) to your label's caption - otherwise you report "failure." (We'll get to multiple MAC addresses in a moment).
Third, and this may not be obvious, but there is a potential memory leak in narayana's function. He creates a new TStringList and returns it. In that case, he can't very well free it, or you'd get nothing useful back. So you have to free his TStringList. This works, but isn't a best practice. I'll suggest a refinement in a moment.
Okay... If the above exercise works, there are several ways to display multiple MAC addresses. This one is easiest: Label1.Caption := myStringList.CommaText;
Isn't that cool? CommaText is a very handy property of TStringList.
Alternately, instead of a label, you might use a TMemo. In that case, your code might look like this: var myStringList; begin myStringList := Get_EthernetAddresses; Memo1.Lines.Assign(myStringList.Strings); // And don't forget! myStringList.Free; end;
The above technique can be used with a ListBox, ComboBox; any component that has a TStrings member.
That fact, and the potential memory leak would tempt me to revise narayana's code just a bit.
Instead of a function returning a TStringList, it could be a procedure or function taking a TStrings parameter. The caller, then, would be responsible for first constructing (or otherwise providing) the parameter's object and passing it to the function. The function would first (just to be thorough), clear the TStrings parameter, then do it's elegant dance and add found MAC addresses to the passed TStrings.
Since the programmer invoking the function would have to first provide the parameter object, it would be more obvious that it has to be freed.
Here's what that might look like: procedure Get_EthernetAddresses(_list : TStrings); ... begin _list.Clear; // just in case // all the same except for creating a TStringList end; // Note: nothing is returned.
Your code, using the above, would then look more like this: var // we don't need one! We'll use Memo1 on our form begin Get_EthernetAddresses(Memo1.Lines); end;
That's it! One line of code.
|