我在Windows 7计算机上运行Delphi XE4。我希望有一个代码库可以识别是否使用CSIDL或KNOWFOLDERID。
有没有办法使用{$ IFDEF XXXXXX)有条件地编译使用部分中的不同文件,并调用基于Windows XP或更低版本的不同功能?
答案 0 :(得分:4)
你很可能不想为此使用条件编译。这样做会强制您为不同版本的操作系统提供不同的可执行文件。这造成了大量的安装复杂性。
处理场景的常用方法是使用运行时分支而不是条件编译。所以你会写这样的代码:
if IsWindowsVistaOrGreater then
DoKnownFolderIDVersion
else
DoCSIDLVersion;
至关重要的一点是,您必须将这些if语句保持在尽可能低的水平。您必须从高级代码中隐藏这些详细信息。从高级代码的角度来看,它必须询问特定文件夹的位置。高级代码不得包含基于版本的任何分支。
复杂的是,您不能对使用旧功能支持平台上可能不存在的API函数的分支使用加载时链接。因此,使用运行时链接而不是加载时间链接。有很多不同的方法可以实现这一点,但对于系统API,使用现代版本的Delphi,延迟加载是一个很好的选择。
就个人而言,我现在不反对使用基于CSIDL的API,因为我个人认为MS不会很快删除功能。但是关于是否使用CSIDL的决定显然是你的。我当然可以理解不再使用这些API的愿望。很明显,微软不希望你这样做。
如果要检查Windows版本支持,则需要使用新版本的帮助程序API。我现在知道它们已被包含在Delphi附带的Windows单元中。也许它们是最新的,但你可能有一个没有它们的版本。在这种情况下,您可以使用这些:
function IsWindowsVersionOrGreater(wMajorVersion, wMinorVersion, wServicePackMajor: Word): Boolean;
function IsWindowsXPOrGreater: Boolean;
function IsWindowsXPSP1OrGreater: Boolean;
function IsWindowsXPSP2OrGreater: Boolean;
function IsWindowsXPSP3OrGreater: Boolean;
function IsWindowsVistaOrGreater: Boolean;
function IsWindowsVistaSP1OrGreater: Boolean;
function IsWindowsVistaSP2OrGreater: Boolean;
function IsWindows7OrGreater: Boolean;
function IsWindows7SP1OrGreater: Boolean;
function IsWindows8OrGreater: Boolean;
function IsWindows8Point1OrGreater: Boolean;
....
const
VER_EQUAL = 1;
VER_GREATER = 2;
VER_GREATER_EQUAL = 3;
VER_LESS = 4;
VER_LESS_EQUAL = 5;
VER_AND = 6;
VER_OR = 7;
_WIN32_WINNT_WINXP = $0501;
_WIN32_WINNT_VISTA = $0600;
_WIN32_WINNT_WIN7 = $0601;
_WIN32_WINNT_WIN8 = $0602;
_WIN32_WINNT_WINBLUE = $0603;
function VerSetConditionMask(dwlConditionMask: ULONGLONG; dwTypeBitMask: DWORD; dwConditionMask: Byte): ULONGLONG; stdcall; external kernel32;
function VerifyVersionInfo(var lpVersionInfo: TOSVersionInfoEx; dwTypeMask: DWORD; dwlConditionMask: DWORDLONG): BOOL; stdcall; external kernel32 name 'VerifyVersionInfoW';
function IsWindowsVersionOrGreater(wMajorVersion, wMinorVersion, wServicePackMajor: Word): Boolean;
var
osvi: TOSVersionInfoEx;
dwlConditionMask: DWORDLONG;
begin
osvi := Default(TOSVersionInfoEx);
osvi.dwOSVersionInfoSize := SizeOf(osvi);
osvi.dwMajorVersion := wMajorVersion;
osvi.dwMinorVersion := wMinorVersion;
osvi.wServicePackMajor := wServicePackMajor;
dwlConditionMask := VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
dwlConditionMask := VerSetConditionMask(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
dwlConditionMask := VerSetConditionMask(dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
Result := VerifyVersionInfo(osvi, VER_MAJORVERSION or VER_MINORVERSION or VER_SERVICEPACKMAJOR, dwlConditionMask);
end;
function IsWindowsXPOrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HiByte(_WIN32_WINNT_WINXP), LoByte(_WIN32_WINNT_WINXP), 0);
end;
function IsWindowsXPSP1OrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HiByte(_WIN32_WINNT_WINXP), LoByte(_WIN32_WINNT_WINXP), 1);
end;
function IsWindowsXPSP2OrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HiByte(_WIN32_WINNT_WINXP), LoByte(_WIN32_WINNT_WINXP), 2);
end;
function IsWindowsXPSP3OrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HiByte(_WIN32_WINNT_WINXP), LoByte(_WIN32_WINNT_WINXP), 3);
end;
function IsWindowsVistaOrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HiByte(_WIN32_WINNT_VISTA), LoByte(_WIN32_WINNT_VISTA), 0);
end;
function IsWindowsVistaSP1OrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HiByte(_WIN32_WINNT_VISTA), LoByte(_WIN32_WINNT_VISTA), 1);
end;
function IsWindowsVistaSP2OrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HiByte(_WIN32_WINNT_VISTA), LoByte(_WIN32_WINNT_VISTA), 2);
end;
function IsWindows7OrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HiByte(_WIN32_WINNT_WIN7), LoByte(_WIN32_WINNT_WIN7), 0);
end;
function IsWindows7SP1OrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HiByte(_WIN32_WINNT_WIN7), LoByte(_WIN32_WINNT_WIN7), 1);
end;
function IsWindows8OrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HiByte(_WIN32_WINNT_WIN8), LoByte(_WIN32_WINNT_WIN8), 0);
end;
function IsWindows8Point1OrGreater: Boolean;
begin
Result := IsWindowsVersionOrGreater(HiByte(_WIN32_WINNT_WINBLUE), LoByte(_WIN32_WINNT_WINBLUE), 0);
end;
function IsWindowsServer: Boolean;
var
osvi: TOSVersionInfoEx;
dwlConditionMask: DWORDLONG;
begin
osvi := Default(TOSVersionInfoEx);
osvi.dwOSVersionInfoSize := SizeOf(osvi);
osvi.wProductType := VER_NT_WORKSTATION;
dwlConditionMask := VerSetConditionMask(0, VER_PRODUCT_TYPE, VER_EQUAL);
Result := not VerifyVersionInfo(osvi, VER_PRODUCT_TYPE, dwlConditionMask);
end;
答案 1 :(得分:0)
{$IFDEF VISTA_UP}
// use modern APIs
{$ELSE}
// fallback
{$ENDIF}
当您的目标是Vista +时,在某处定义了VISTA_UP
条件符号,例如:
-Dxxx
命令行编译器开关$DEFINE VISTA_UP
在单独的$INCLUDE
- d文件中,包含所有其他编译时配置内容请记住,您无法保留图书馆单元的DCU,每次切换目标时都必须重建。