Delphi:如何确定应用程序是否在Win32 / Win64下运行并在64位时自动启动64位版本?

时间:2018-06-07 04:30:46

标签: delphi 32bit-64bit

情况

我打算将我的Delphi(XE6)GUI应用程序的32位和64位版本捆绑在Zip存档中。

注意:在我们假设的这个问题中,用户提取了整个存档,即没有直接从存档管理器运行可执行文件。

所以,我们假设我们已经提取了存档并有两个文件:

  1. program.exe

  2. program64.exe

  3. 为了清楚起见,命名约定是32位版本在其名称中没有除程序名称之外的任何内容,并且64位版本具有与64后缀完全相同的程序名称

    意图

    如果用户在64位Windows计算机上运行32位版本,我希望它能够检测到它,然后关闭它并运行64位版本。

    注意

    在我自己的回答中,我将在使用代码期间记录我的所有发现,随时添加更好的答案或替代方案,如果它确实做出了一些贡献,我肯定会投票。也许更重要的是,请对您发现错误的特定部分发表评论。

1 个答案:

答案 0 :(得分:0)

启动其他可执行文件

首先,我们需要一个能够启动其他可执行文件的函数,我的通用示例如下,您可以根据需要使用它来启动几乎任何其他可执行文件:

function LaunchExecutableFile(const ExecutableFilePath, Parameters: string; const ShowCmd: Integer): Boolean;
begin
  Result := Winapi.ShellAPI.ShellExecute(Application.MainFormHandle, 'open', PChar(StringFunctions.DoubleQuoteStr(ExecutableFilePath)), PChar(Parameters), nil, ShowCmd) > 32;
end;

注意:

  1. 我故意添加了Winapi.ShellAPI...这样的可选命名空间,以便您确切知道这些函数的定义位置。

  2. 定义了32个错误代码,这就是True的结果大于ShellExecute时函数返回32的原因。

  3. 我定义了函数DoubleQuoteStr,因为如果路径中有一些空格,系统会在每个空格中查找文件,从而查找错误的路径。这是一个非常简单的功能,它是完全可选的,它只是优化。这也是通用函数如下:

    function DoubleQuoteStr(S: string): string;
    begin
      if (S = '') or (S = '"')
        then S := '""'
        else begin
          if S[1] <> '"' then S := '"' + S;
          if S[System.Length(S)] <> '"' then S := S + '"';
        end;
      Result := S;
    end;
    
  4. 可悲的是,我仍然不确定第一个ShellExecute HWND参数,更具体地说,如果我的通用方法是正确的,请随时纠正我!

  5. 检测64位系统

    其次,我们需要一个能够检测64位系统的函数,更具体地说,如果可执行文件在WOW64下运行。

    function IsWow64Process: Boolean;
    
    type
      TIsWow64Process = function(AHandle: DWORD; var AIsWow64: BOOL): BOOL; stdcall;
    
    var
      hIsWow64Process: TIsWow64Process;
      hKernel32: DWORD;
      IsWow64: BOOL;
    
    begin
      Result := False;
    
      hKernel32 := Winapi.Windows.LoadLibrary('kernel32.dll');
      if hKernel32 = 0 then Exit;
    
      try
        @hIsWow64Process := Winapi.Windows.GetProcAddress(hKernel32, 'IsWow64Process');
        if not System.Assigned(hIsWow64Process) then Exit;
    
        IsWow64 := False;
        if hIsWow64Process(Winapi.Windows.GetCurrentProcess, IsWow64) then
          Result := IsWow64;
    
      finally
        Winapi.Windows.FreeLibrary(hKernel32);
      end;
    end;
    

    注意:

    1. 如您所见,该函数从中加载了库kernel32.dll和函数IsWow64Process

    2. 应该采取一切安全措施,以便返回正确的结果。

    3. 运行程序

      最后,我们需要调整dpr文件。

      在变量部分,添加:

      var
      {$IFNDEF WIN64}
        App64: string;
      {$ENDIF}
      

      将您的主要begin - end部分纳入另一个begin - end

      并在开头添加这样的内容:

      {$IFNDEF WIN64}
      
        App64 := System.SysUtils.ChangeFileExt(Application.ExeName, '64.exe');
      
        if not (ProcessFunctions.IsWow64Process and System.SysUtils.FileExists(App64) and
                ProcessFunctions.LaunchExecutableFile(App64, '', SW_SHOWNORMAL)) then
      
      {$ENDIF}