我们最近从 Delphi 柏林更新到Alexandria 11.2,遇到了一个问题。我们的一个应用程序针对64位平台。当它连接查询Windows服务时,它抛出一个范围检查错误。它在针对32位时不会这样做;在柏林/64位中也不会发生这种情况。我比较了两种环境之间的64位编译选项,没有发现任何差异。
function TForm1.ConnectToServices(const AServiceName: String; const AMachineName: String): Integer;
begin
Result := -1;
try
if AMachineName = EmptyStr then
// Error happens here
Result := OpenSCManager(nil, nil, SC_MANAGER_CONNECT)
else
// and here.
Result := OpenSCManager(PChar(AMachineName), nil, SC_MANAGER_CONNECT);
except
// Get last error return 0, but ignoring the above error causes problems downstream
ShowMessage(SysErrorMessage(GetLastError));
end;
end;
字符串
我真的不知道是什么原因造成的,以及如何解决它。
将64位编译器选项设置为与柏林的选项相匹配,其中dll调用成功而没有问题。
1条答案
按热度按时间8ehkhllq1#
简短的回答:
OpenSCManager()
返回的64位句柄不适合32位整数。更长的答案:
在Windows中,句柄为
VOID pointers
( Delphi 中的THandle
),这意味着对于32位代码,它们是4个字节,对于64位代码,它们是8个字节。当句柄需要在进程间共享时,8字节句柄的前4个字节全为零。这使得它们可以被32位和64位进程使用。对于64位代码,在进程之间不共享的句柄可以使用全部64位。从 Delphi 11.2开始,高熵内存分配器默认启用。这意味着任何内存地址,即使在不使用太多内存的程序中,通常也不会将前32位设置为全零,因此它们不适合32位变量。通过32位变量传递64位地址一直是一个错误,但现在更容易触发此类错误。