您的代码无法在任何地方编译。 VCL 和 FMX 都不是。所以,这个问题根本与 FMX 无关。也许早期版本有,但不是这里的代码。
我认为@TLama 与您的使用条款走在正确的轨道上。您需要来自ActiveX 单元的IEnumVARIANT,而不是来自Ole2 的那个。 Ole2 中的 IEnumVARIANT 的问题在于它缺少其 GUID,这意味着 as 转换失败。而Ole2 中的IUnknown 是一个很奇怪的类。而Ole2 中的IEnumVARIANT._Next 对var 参数使用有符号整数,这也很奇怪。所以,Ole2 似乎是个坏消息!
另外,您缺少VarIsNull 所需的Variants 单元。
这个版本的代码运行成功:
{$APPTYPE CONSOLE}
uses
System.Variants,
Winapi.ActiveX,
System.Win.ComObj;
function GetFirstMacAddress : String;
const
wbemFlagForwardOnly = $00000020;
var
FSWbemLocator : OLEVariant;
FWMIService : OLEVariant;
FWbemObjectSet: OLEVariant;
FWbemObject : OLEVariant;
oEnum : IEnumvariant;
iValue : LongWord;
begin
Result := '';
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
FWbemObjectSet:= FWMIService.ExecQuery('SELECT Description,MACAddress FROM Win32_NetworkAdapterConfiguration','WQL',wbemFlagForwardOnly);
oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
while oEnum.Next(1, FWbemObject, iValue) = 0 do
begin
if not VarIsNull(FWbemObject.MACAddress) then
begin
Result := (FWbemObject.MACAddress);
exit;
end;
FWbemObject:=Unassigned;
end;
end;
begin
CoInitialize(nil);
Writeln(GetFirstMacAddress);
Readln;
end.
这可能就回到了你开始的地方!您不想在 FMX 代码中使用 ActiveX。但是Ole2 也不好。您需要做的就是在您的代码中对IEnumVARIANT 进行本地声明。无需占用整个ActiveX 单元。
所以从上面的代码开始。移除ActiveX 单元。并提供从ActiveX 单元源复制的IEnumVARAINT 的良好声明。
FWIW,我不会用 WMI 解决这个问题。它非常重量级,手头的任务不需要它。
以下是获取本地网络接口的 MAC 地址的方法:
{$APPTYPE CONSOLE}
uses
System.SysUtils,
Winapi.Windows,
Winapi.WinSock;
type
TMacAddress = array [0..5] of Byte;
function SendARP(DestIP, SrcIP: ULONG; pMacAddr: Pointer; var PhyAddrLen: ULONG): DWORD; stdcall; external 'Iphlpapi.dll';
procedure InitializeWinSock;
var
wsaData: TWSADATA;
begin
Win32Check(Winapi.WinSock.WSAStartup($0202, wsaData)=0);
end;
procedure FinalizeWinSock;
begin
Winapi.WinSock.WSACleanup;
end;
function inet_addr(const IPAddress: string): ULONG;
begin
Result := ULONG(Winapi.WinSock.inet_addr(PAnsiChar(AnsiString(IPAddress))));
end;
function GetMacAddress(const IPAddress: string): TMacAddress;
var
MaxMacAddrLen: ULONG;
begin
MaxMacAddrLen := SizeOf(Result);
if SendARP(inet_addr(IPAddress), 0, @Result, MaxMacAddrLen)<>NO_ERROR then begin
raise Exception.CreateFmt('Unable to do SendARP on address: ''%s''', [IPAddress]);
end;
end;
var
i: Integer;
mac: TMacAddress;
begin
InitializeWinSock;
mac := GetMacAddress('localhost');
for i := low(mac) to high(mac) do
begin
Write(IntToHex(mac[i], 2));
if i<high(mac) then
Write(':');
end;
Writeln;
FinalizeWinSock;
Readln;
end.