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 the Win32_NetworkAdapter class instead. It has the PhysicalAdapter
member. The following example should list you the MAC addresses of physical adapters:
program Program1;
{$APPTYPE CONSOLE}
uses
SysUtils, ActiveX, ComObj, Variants;
procedure GetWin32_NetworkAdapterInfo;
const
WbemUser = '';
WbemPassword = '';
WbemComputer = 'localhost';
wbemFlagForwardOnly = $00000020;
var
ElementCount: LongWord;
FWMIService: OleVariant;
FWbemObject: OleVariant;
EnumVariant: IEnumVARIANT;
FSWbemLocator: OleVariant;
FWbemObjectSet: OleVariant;
begin;
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer(WbemComputer, 'root\CIMV2', WbemUser, WbemPassword);
FWbemObjectSet := FWMIService.ExecQuery('SELECT * FROM Win32_NetworkAdapter WHERE PhysicalAdapter = 1', 'WQL', wbemFlagForwardOnly);
EnumVariant := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
while EnumVariant.Next(1, FWbemObject, ElementCount) = 0 do
begin
Writeln(Format('MACAddress %s', [VarToStr(FWbemObject.MACAddress)]));
FWbemObject := Unassigned;
end;
end;
begin
try
CoInitialize(nil);
try
GetWin32_NetworkAdapterInfo;
finally
CoUninitialize;
end;
except
on E:EOleException do
Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode]));
on E:Exception do
Writeln(E.Classname, ':', E.Message);
end;
Writeln('Press Enter to exit');
Readln;
end.
Based on the code generated by the WMI Delphi Code Creator.
Update:
You are actually trying to filter out the adapters which belongs to virtual machines, what is not that easy since they are simulated like to be as physical ones (you can even see them in Device Manager as the physical adapters), so you cannot distinguish them e.g.:
DHCPEnabled
member of the Win32_NetworkAdapter class, because even virtual machines might be configured so they get IP address from a DHCP serverAdapterTypeId
member of the Win32_NetworkAdapter class, since there is no special type for virtual adaptersPhysicalAdapter
member of the Win32_NetworkAdapter class, because they are being simulated to be physicalAdditional reading:
Find only physical network adapters with WMI Win32_NetworkAdapter class - this article has a good analysis and it might fulfill your needs (I haven't tested it though)
How to determine physical network adapter type using WMI - this question is opened at this time and it is actually exactly what you need
How to determine MAC Address of the physical network card - there is one idea I like and I would personally stick to when I'd be 100% sure that the root of the PNPDeviceID
member
of the Win32_NetworkAdapter class for hardware adapters cannot start with something different from the PCI\\
(actually the same I was thinking about when I was comparing the data)
You could also use GetAdaptersAddresses API from the IP Helper library. For a Delphi translation, Magenta Systems IP Helper Component looks good at first glance.