2022年6月15日

現在実行している環境(プロセッサアーキテクチャ)を調べる

Windowsの実行環境としては、現時点(2022年06月)でx86(32bit)版、x64(64bit)版、ARM版があります。一方でDelphiがサポートするターゲットプラットフォームにはWindows 32ビット(x86)、Windows 64ビット(x64)があります。組み合わせとして、x86のプログラムはx86、x64、ARMのいずれでも、またx64のプログラムはx64、ARM(Windows 11のみ)で動作します。逆に動作しない組み合わせはx64のプログラムとx86、ARM(Windows 10)ということになります(Delphiではいまのところ作れませんが、ARMのプログラムはx86/x64では動作せず、ARM版でのみ動作します)。これはWindowsのWOW64(エミュレータ)やDynamic Binary Translator(JIT)によるもので、後方互換性を極めて重視するMicrosoftらしいよくできた仕組みです。これによりWindows上で動作するプログラムは実行環境のことをあまり気にしなくてもよいのですが、まれに(ターゲットプラットフォームではなく)実行環境によって動作を変えたい、ということがあります。
実行環境を調べるにはいくつかの方法がありますが、IsWow64Process2() を使わずにWowA64を検出する · GitHubによると、Windows 10 Version 1511以降であればWin32APIのIsWow64Process2を、それ以前(Windows XP/Vista/7/8/8.1/10 Version 1507(RTM))であればWin32APIのGetNativeSystemInfoを使うのがよいようです(Windows 2000ではGetSystemInfo)。それでは実装してみましょう。
type
{$SCOPEDENUMS ON}
  TProcessorArchitecture = (x86,   // Intel x86
                            x64,   // AMD64/Intel 64
                            ARM);  // ARM

  TIsWow64Process2Func = function (hProcess: THandle; var ProcessMachine: USHORT; var NativeMachine: USHORT): BOOL; stdcall;
  TGetSystemInfoFunc = procedure (var lpSystemInfo: TSystemInfo); stdcall;

const
  IMAGE_FILE_MACHINE_ARM64 = $AA64;

function GetProcessorArchitecture: TProcessorArchitecture;
var
  IsWow64Process2Func: TIsWow64Process2Func;
  ProcessMachine: USHORT;
  NativeMachine: USHORT;
  GetSystemInfoFunc: TGetSystemInfoFunc;
  SI: TSystemInfo;
begin

  { Use IsWow64Process2 on Windows 10 Version 1511 or later }
  @IsWow64Process2Func := GetProcAddress(GetModuleHandle(kernel32),'IsWow64Process2');
  if Assigned(IsWow64Process2Func) = True then
  begin
    if IsWow64Process2Func(GetCurrentProcess,ProcessMachine,NativeMachine) = True then
    begin
      case NativeMachine of
        IMAGE_FILE_MACHINE_I386:
        begin
          Result := TProcessorArchitecture.x86;
          Exit;
        end;

        IMAGE_FILE_MACHINE_AMD64:
        begin
          Result := TProcessorArchitecture.x64;
          Exit;
        end;

        IMAGE_FILE_MACHINE_ARM64:
        begin
          Result := TProcessorArchitecture.ARM;
          Exit;
        end;
      end;
    end;
  end;

  { Use GetNativeSystemInfo (Windows XP or later) or GetSystemInfo (Windows 2000) }
  FillChar(SI,SizeOf(SI),0);
  @GetSystemInfoFunc := GetProcAddress(GetModuleHandle(kernel32),'GetNativeSystemInfo');
  if Assigned(GetSystemInfoFunc) = True then
  begin
    GetSystemInfoFunc(SI);
  end
  else
  begin
    GetSystemInfo(SI);
  end;

  if SI.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_AMD64 then
  begin
    Result := TProcessorArchitecture.x64;
  end
  else
  begin
    Result := TProcessorArchitecture.x86;
  end;

end;
IsWow64Process2、GetNativeSystemInfo、GetSystemInfoの順にフォールバックして情報を取得するようになっています。

0 件のコメント: