I would like to use a unique identifier to determine whether my application moved to a different computer. The MAC address seems to be suitable for this purpose. The code I use is this:
Procedure TForm4.GetMacAddress;
var item: TListItem;
objWMIService : OLEVariant;
colItems : OLEVariant;
colItem : OLEVariant;
oEnum : IEnumvariant;
iValue : LongWord;
wmiHost, root, wmiClass: string;
i: Int32;
function GetWMIObject(const objectName: String): IDispatch;
var
chEaten: Integer;
BindCtx: IBindCtx;//for access to a bind context
Moniker: IMoniker;//Enables you to use a moniker object
begin
OleCheck(CreateBindCtx(0, bindCtx));
OleCheck(MkParseDisplayName(BindCtx, StringToOleStr(objectName), chEaten, Moniker));//Converts a string into a moniker that identifies the object named by the string
OleCheck(Moniker.BindToObject(BindCtx, nil, IDispatch, Result));//Binds to the specified object
end;
begin
wmiHost := '.';
root := 'root\CIMV2';
wmiClass := 'Win32_NetworkAdapterConfiguration';
objWMIService := GetWMIObject(Format('winmgmts:\\%s\%s',[wmiHost,root]));
colItems := objWMIService.ExecQuery(Format('SELECT * FROM %s',[wmiClass]),'WQL',0);
oEnum := IUnknown(colItems._NewEnum) as IEnumVariant;
i := 0;
while oEnum.Next(1, colItem, iValue) = 0 do
begin
Item := View.Items.Add;
item.Caption := Copy (colItem.Caption, 2, 8);
Item.SubItems.Add (colItem.Description);
Item.SubItems.Add (colItem.ServiceName);
Item.SubItems.Add (VarToStrNil (colItem.MACAddress));
if (VarToStrNil(colItem.MACAddress) <> '')
then Item.SubItems.Add ('yes')
else Item.SubItems.Add ('no');
if colItem.IPEnabled
then Item.SubItems.Add ('yes')
else Item.SubItems.Add ('no');
Item.SubItems.Add (VarToStrNil (colItem.SettingID));
Item.SubItems.Add (IntToStr (colItem.InterfaceIndex));
end; // if
end; // GetMacAddress //
My machine has one network port, but this code finds 18 network related ports/things/whatever. Among them there are four MAC adresses. I presume that a network port should be IP enabled so that leaves two left (labeled MAC in the image). Is it correct to assume that of the ports thus filtered, the one with the lowest index is the hardware port?
Edit in the snapshot above the Realtek adapter is the only physical adapter in the machine. The other adapter is the VirtualBox virtual adapter. The answer of TLama identifies these two adapters, but is there a way to find the address of the only Physical (Realtek) adapter?
Update 1 EJP pointed out that the MAC address can be changed. This somewhat undermines my purpose, but as I am looking for a solution that fits most situations I decided to live with it.
TLama and TOndrej pointed to several solutions. Both end up with a situation that a physical adapter could not be found without any doubt.
Update 2 TLama's excellent reading list shows that there is probably not a certain way to determine the physical adapter. The article mentioned in the first bullet shows how to shrink the amount of adapters based on some simple assumptions. The article in the third bullet shows how to select the adapter connected to the PCI bus, which is in fact exactly what I wanted to know. There are some weird exceptions mentioned in the article but I think this will provide an answer in most cases.
Thank you all for your contributions!