2

Windows 7 マシンで Delphi XE4 を実行しています。CSIDL と KNOWFOLDERID のどちらを使用するかを認識できる 1 つのコード ベースが必要です。

{$IFDEF XXXXXX) を使用して、uses セクションでさまざまなファイルを条件付きでコンパイルし、Windows XP 以前に基づいてさまざまな関数を呼び出す方法はありますか?

4

2 に答える 2

4

これに条件付きコンパイルを使用したくない可能性が非常に高いです。これを行うと、オペレーティング システムのバージョンごとに異なる実行可能ファイルを出荷する必要があります。これにより、インストールが非常に複雑になります。

このシナリオに対処するための通常のアプローチは、条件付きコンパイルではなくランタイム ブランチを使用することです。したがって、次のようなコードを記述します。

if IsWindowsVistaOrGreater then
  DoKnownFolderIDVersion
else
  DoCSIDLVersion;

重要なことの 1 つは、これらの if ステートメントをできるだけ低いレベルに保つ必要があるということです。これらの詳細を高レベル コードから隠す必要があります。高レベル コードの観点からは、特定のフォルダーの場所を要求する必要があります。高レベル コードには、バージョンに基づく分岐が含まれていてはなりません。

複雑なのは、サポートされている古いプラットフォームには存在しない可能性がある API 関数を使用するブランチには、ロード時のリンクを使用できないことです。そのため、読み込み時のリンクではなく、実行時のリンクを使用してください。これを実現するにはさまざまな方法がありますが、システム API の場合、Delphi の最新バージョンでは、遅延読み込みが優れたオプションです。


個人的には、MS がすぐに機能を削除するとは思わないので、今でも CSIDL ベースの API を使用することを嫌いではありません。しかし、CSIDL を使用するかどうかの決定は、明らかにあなた次第です。これらの API をもう使用したくないという気持ちは確かに理解できます。Microsoft があなたにそうしてほしくないことは明らかです。


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;
于 2014-07-06T16:37:17.283 に答える
0
{$IFDEF VISTA_UP}
// use modern APIs
{$ELSE}
// fallback
{$ENDIF}

ターゲットが Vista+ の場合、次のように条件付きシンボルをどこかVISTA_UPに定義します。

  • 「プロジェクトオプション」の「ディレクトリ/条件」の下
  • -Dxxxコマンドライン コンパイラ スイッチの使用
  • または、他のすべてのコンパイル時の構成要素を含む$DEFINE VISTA_UP別の$INCLUDE-d ファイルで

ライブラリ ユニットの DCU を保持することはできません。ターゲットを切り替えるたびに再構築する必要があります。

于 2014-07-06T16:20:39.947 に答える