我终于硬着头皮买了 XE6,不出所料,Unicode 转换变成了一场噩梦。因此,如果有人能告诉我为什么这个简单的 Windows API 调用失败,那将不胜感激。该函数不返回错误,第一次调用获得正确的缓冲区长度,第二次调用用垃圾填充记录。
这在 Delphi 2007 下工作正常,但在 XE6 上失败,pAdapterinfo 返回记录中有 unicode 垃圾,即使它在 IpTypes.pas 中使用 AnsiString 显式声明
系统是 Win7(64) 但编译为 32 位。
uses iphlpapi, IpTypes;
function GetFirstAdapterMacAddress:AnsiString;
var pAdapterInfo:PIP_ADAPTER_INFO;
BufLen,Status:cardinal; i:Integer;
begin
result:='';
BufLen:= sizeof(IP_ADAPTER_INFO);
GetAdaptersInfo(nil, BufLen);
pAdapterInfo:= AllocMem(BufLen);
try
Status:= GetAdaptersInfo(pAdapterInfo,BufLen);
if (Status <> ERROR_SUCCESS) then
begin
case Status of
ERROR_NOT_SUPPORTED: raise exception.create('GetAdaptersInfo is not supported by the operating ' +
'system running on the local computer.');
ERROR_NO_DATA: raise exception.create('No network adapter on the local computer.');
else
raiselastOSerror;
end;
Exit;
end;
while (pAdapterInfo^.AddressLength=0) and (pAdapterInfo^.next<>nil) do
pAdapterInfo:=pAdapterInfo.next;
if pAdapterInfo^.AddressLength>0 then
for i := 0 to pAdapterInfo^.AddressLength - 1 do
result := result + IntToHex(pAdapterInfo^.Address[I], 2);
finally
Freemem(pAdapterInfo);
end;
end;
更新:
我又做了一些检查。我用一个表单和一个按钮创建了一个新的简单应用程序,并在按下按钮并且它工作时调用了例程。
不同之处在于......在工作形式中,IP_ADAPTER_INFO 的大小为 640 字节。
在更复杂的应用程序中使用此例程时,它会失败,并且 IP_ADAPTER_INFO 的大小显示为 1192 字节。
此时,编译器似乎单方面决定将结构中的 ansi 字符类型更改为 unicode 字符。调试器以 unicode 形式显示 AdapterName 和描述字段。我对系统源代码进行了 grep,除了 Indy 库之外,在库代码中没有声明此数据类型的其他版本,这只是一个副本。
这是IPtypes中的数据结构定义
PIP_ADAPTER_INFO = ^IP_ADAPTER_INFO;
{$EXTERNALSYM PIP_ADAPTER_INFO}
_IP_ADAPTER_INFO = record
Next: PIP_ADAPTER_INFO;
ComboIndex: DWORD;
AdapterName: array [0..MAX_ADAPTER_NAME_LENGTH + 3] of AnsiChar;
Description: array [0..MAX_ADAPTER_DESCRIPTION_LENGTH + 3] of AnsiChar;
AddressLength: UINT;
Address: array [0..MAX_ADAPTER_ADDRESS_LENGTH - 1] of BYTE;
Index: DWORD;
Type_: UINT;
DhcpEnabled: UINT;
CurrentIpAddress: PIP_ADDR_STRING;
IpAddressList: IP_ADDR_STRING;
GatewayList: IP_ADDR_STRING;
DhcpServer: IP_ADDR_STRING;
HaveWins: BOOL;
PrimaryWinsServer: IP_ADDR_STRING;
SecondaryWinsServer: IP_ADDR_STRING;
LeaseObtained: time_t;
LeaseExpires: time_t;
end;
看起来像一个编译器错误。