如何检测特定的Delphi版本当前是否正在运行?

发布于 2025-01-09 04:27:32 字数 1538 浏览 1 评论 0原文

在 Delphi 11 Alexandria 中 Windows 10 上的 32 位 VCL 应用程序中,我尝试检测当前是否正在运行特定的 Delphi 版本。因此,我使用 Winapi.TlHelp32.CreateToolhelp32Snapshot 函数来搜索“bds.exe”:

function ProcessExists(exeFileName: string): Boolean;
var
  ContinueLoop: Winapi.Windows.BOOL;
  FSnapshotHandle: Winapi.Windows.THandle;
  FProcessEntry32: Winapi.TlHelp32.TProcessEntry32;
begin
  FSnapshotHandle := Winapi.TlHelp32.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  FProcessEntry32.dwSize := System.SizeOf(FProcessEntry32);
  ContinueLoop := Winapi.TlHelp32.Process32First(FSnapshotHandle, FProcessEntry32);
  Result := False;
  while Integer(ContinueLoop) <> 0 do
  begin
    if SameText(ExtractFileName(FProcessEntry32.szExeFile), ExeFileName) or SameText(FProcessEntry32.szExeFile, ExeFileName) then
    begin
      Result := True;
      CodeSite.Send('ProcessExists: FProcessEntry32.szExeFile', FProcessEntry32.szExeFile);
      BREAK;
    end;
    ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
  end;
  Winapi.Windows.CloseHandle(FSnapshotHandle);
end;
...
CodeSite.Send('ProcessExists(ThisBdsExe)', ProcessExists('bds.exe'));

不幸的是,FProcessEntry32.szExeFile 仅返回 FILENAME,而没有 PATH 信息。所以我只得到 Delphi 是否正在运行的信息,而不是特定 Delphi 版本是否正在运行的信息!

有没有办法从 FProcessEntry32 结构中获取 PATH 信息?

当然,我知道我的计算机上存在的每个 bds.exe 的路径。但这不起作用:

CodeSite.Send('ProcessExists(Delphi 11 bds.exe path)', ProcessExists('C:\Program Files (x86)\Embarcadero\Studio\22.0\bin\bds.exe'));

In a 32-bit VCL application on Windows 10 in Delphi 11 Alexandria, I try to detect whether a specific Delphi version is currently running. So I used the Winapi.TlHelp32.CreateToolhelp32Snapshot function to search for "bds.exe":

function ProcessExists(exeFileName: string): Boolean;
var
  ContinueLoop: Winapi.Windows.BOOL;
  FSnapshotHandle: Winapi.Windows.THandle;
  FProcessEntry32: Winapi.TlHelp32.TProcessEntry32;
begin
  FSnapshotHandle := Winapi.TlHelp32.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  FProcessEntry32.dwSize := System.SizeOf(FProcessEntry32);
  ContinueLoop := Winapi.TlHelp32.Process32First(FSnapshotHandle, FProcessEntry32);
  Result := False;
  while Integer(ContinueLoop) <> 0 do
  begin
    if SameText(ExtractFileName(FProcessEntry32.szExeFile), ExeFileName) or SameText(FProcessEntry32.szExeFile, ExeFileName) then
    begin
      Result := True;
      CodeSite.Send('ProcessExists: FProcessEntry32.szExeFile', FProcessEntry32.szExeFile);
      BREAK;
    end;
    ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
  end;
  Winapi.Windows.CloseHandle(FSnapshotHandle);
end;
...
CodeSite.Send('ProcessExists(ThisBdsExe)', ProcessExists('bds.exe'));

Unfortunately, FProcessEntry32.szExeFile returns only the FILENAME without the PATH information. So I get only the information whether Delphi is running, but NOT whether a specific Delphi version is running!

Is there any way to get the PATH information from the FProcessEntry32 structure?

Of course, I know the paths of each bds.exe that exists on my computer. But this does not work:

CodeSite.Send('ProcessExists(Delphi 11 bds.exe path)', ProcessExists('C:\Program Files (x86)\Embarcadero\Studio\22.0\bin\bds.exe'));

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

坏尐絯℡ 2025-01-16 04:27:33

GetModuleFileNameEx 对我有用:

function GetPathFromPID(const PID: cardinal): string;
var
  hProcess: THandle;
  path: array[0..MAX_PATH - 1] of char;
begin
  hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false, PID);
  if hProcess <> 0 then
  try
    if GetModuleFileNameEx(hProcess, 0, path, MAX_PATH) = 0 then
      RaiseLastOSError;
    result := path;
  finally
    CloseHandle(hProcess)
  end
  else
    RaiseLastOSError;
end;

function ProcessExists(exeFileName: string): Boolean;
var
  ContinueLoop: Winapi.Windows.BOOL;
  FSnapshotHandle: Winapi.Windows.THandle;
  FProcessEntry32: Winapi.TlHelp32.TProcessEntry32;
begin
  FSnapshotHandle := Winapi.TlHelp32.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  FProcessEntry32.dwSize := System.SizeOf(FProcessEntry32);
  ContinueLoop := Winapi.TlHelp32.Process32First(FSnapshotHandle, FProcessEntry32);
  Result := False;
  var ThisExeName := ExtractFileName(exeFileName);
  while Integer(ContinueLoop) <> 0 do
  begin
    if SameText(ExtractFileName(FProcessEntry32.szExeFile), ThisExeName) or SameText(FProcessEntry32.szExeFile, ThisExeName) then
    begin
      var ThisBdsExePath := GetPathFromPID(FProcessEntry32.th32ProcessID);
      Result := SameText(exeFileName, ThisBdsExePath);
      if Result then BREAK;
    end;
    ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
  end;
  Winapi.Windows.CloseHandle(FSnapshotHandle);
end;

GetModuleFileNameEx worked for me:

function GetPathFromPID(const PID: cardinal): string;
var
  hProcess: THandle;
  path: array[0..MAX_PATH - 1] of char;
begin
  hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false, PID);
  if hProcess <> 0 then
  try
    if GetModuleFileNameEx(hProcess, 0, path, MAX_PATH) = 0 then
      RaiseLastOSError;
    result := path;
  finally
    CloseHandle(hProcess)
  end
  else
    RaiseLastOSError;
end;

function ProcessExists(exeFileName: string): Boolean;
var
  ContinueLoop: Winapi.Windows.BOOL;
  FSnapshotHandle: Winapi.Windows.THandle;
  FProcessEntry32: Winapi.TlHelp32.TProcessEntry32;
begin
  FSnapshotHandle := Winapi.TlHelp32.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  FProcessEntry32.dwSize := System.SizeOf(FProcessEntry32);
  ContinueLoop := Winapi.TlHelp32.Process32First(FSnapshotHandle, FProcessEntry32);
  Result := False;
  var ThisExeName := ExtractFileName(exeFileName);
  while Integer(ContinueLoop) <> 0 do
  begin
    if SameText(ExtractFileName(FProcessEntry32.szExeFile), ThisExeName) or SameText(FProcessEntry32.szExeFile, ThisExeName) then
    begin
      var ThisBdsExePath := GetPathFromPID(FProcessEntry32.th32ProcessID);
      Result := SameText(exeFileName, ThisBdsExePath);
      if Result then BREAK;
    end;
    ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
  end;
  Winapi.Windows.CloseHandle(FSnapshotHandle);
end;
同展鸳鸯锦 2025-01-16 04:27:32

PROCESSENTRY32' 的 API 帮助s szExeFile 条目:

szExeFile

进程的可执行文件的名称。要检索完整的
可执行文件的路径,调用Module32First函数并检查
返回的 MODULEENTRY32 结构的 szExePath 成员。
但是,如果调用进程是32位进程,则必须调用
QueryFullProcessImageName 函数检索完整路径
64 位进程的可执行文件。

因此,您需要进行 Module32First 调用,并且目前至少 BDS 是 32 位进程,因此即使您的应用程序是 32 位,您也不需要使用 QueryFullProcessImageName。

The API help for PROCESSENTRY32's szExeFile entry:

szExeFile

The name of the executable file for the process. To retrieve the full
path to the executable file, call the Module32First function and check
the szExePath member of the MODULEENTRY32 structure that is returned.
However, if the calling process is a 32-bit process, you must call the
QueryFullProcessImageName function to retrieve the full path of the
executable file for a 64-bit process.

So you need to make a Module32First call and currently at least BDS is a 32bit process so you don't need to use QueryFullProcessImageName even if your app is 32bit.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文