代码之家  ›  专栏  ›  技术社区  ›  Vlastimil Burián

delphi:如何确定应用程序是否在win32/win64下运行,如果在64位,如何自动启动64位版本?

  •  0
  • Vlastimil Burián  · 技术社区  · 6 年前

    情况

    我打算将我的delphi(xe6)gui应用程序的32位和64位版本捆绑在一个zip存档中。

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

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

    1. program.exe

    2. program64.exe

    明确地说,命名约定是32位版本的名称中除了程序名之外没有其他内容,64位版本的程序名与 64 后缀。

    意图

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

    音符

    在我自己的答案中,我将记录我在使用代码期间的所有发现,随时可以添加更好的答案或备选方案,如果它真的做出了一些贡献,我一定会投赞成票。或许更重要的是,请对你发现错误的部分进行评论。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Vlastimil Burián    6 年前

    启动其他可执行文件

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

    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. 遗憾的是,我仍然不确定 贝壳执行 HWND 争论,更具体地说,如果我的一般方法是正确的,请随意纠正我!


    检测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. 每项安全措施都应到位,以便返回正确的结果。


    运行程序

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

    在“变量”部分中,添加:

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

    把你的主菜包起来 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}