2014-02-06 26 views
0

我正在使用Delphi XE4。XE4 Firemonkey OLE類型轉換錯誤(取得win MAC地址)

我正在將一段編譯好的代碼移植到vcl下(使用ActiveX,vcl.oleauto)到firemonkey友好版本中。

它引發無效的類型轉換錯誤。任何人都知道vcl單元和這些單元有什麼不同?

謝謝

約翰。

uses 

{$IFDEF MSWINDOWS} 
    Winapi.Windows, 
    System.Win.ComObj, 
    Winapi.ole2, 
{$ENDIF} 

SysUtils; 


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; 

回答

1

您的代碼無法在任何地方編譯。無論是VCL還是FMX。所以,這個問題根本與FMX無關。也許是早期版本,但不是這裏的代碼。

我認爲@TLama的使用條款是正確的。您需要ActiveX單元中的IEnumVARIANT單元,而不是Ole2中的單元。 Ole2IEnumVARIANT的問題在於它缺少其GUID,這意味着as轉換失敗。 Ole2中的IUnknown是一個很奇怪的類。 Ole2中的IEnumVARIANT._Nextvar參數使用有符號整數,這也很奇怪。所以,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. 
+0

感謝的是,它比以前的版本更輕的重量。 – John