【发布时间】:2014-06-27 03:41:01
【问题描述】:
我终于硬着头皮买了 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;
看起来像一个编译器错误。
【问题讨论】:
-
GetAdaptersInfo(nil, BufLen);这个电话的目的是什么? -
在 XE2、W7 上工作正常。
-
第一次调用获取propoer缓冲区长度。在 XE2 中工作?所以这是 XE6 特有的一些问题。
-
好的,谢谢。它真的只是 API,我猜不出它是怎么搞砸的。检查
_IP_ADAPTER_INFO是否有任何不同。 -
1192 是所有 AnsiChars 都是 Chars 时的大小,包括来自
IP_ADDR_STRING的那些。多么奇怪!...
标签: delphi delphi-xe6