【问题标题】:Determine the parent process of the current app确定当前app的父进程
【发布时间】:2010-12-23 20:14:57
【问题描述】:

我编写了这个实用程序 (exe),可以从这个主机应用程序中调用它。 而且我更希望该实用程序只能从主机应用程序中调用。 从外部或其他主机运行它应该立即终止该实用程序。

有没有办法找出哪个进程启动了我的实用程序?

感谢您的回复。

【问题讨论】:

  • 我有 SysInternals ProcessExplorer,它向我展示了所有当前正在运行的进程的树以及每个进程是由什么启动的,因此信息绝对可用。问题是如何访问它,不幸的是,我不知道。我将在您的帖子中添加“winapi”标签,让您更清楚地知道这就是您要查找的内容。
  • 我见过的最佳答案是stackoverflow.com/a/3346055/647492

标签: delphi winapi


【解决方案1】:

您可以使用CreateToolhelp32Snapshot 函数枚举正在运行的进程列表,然后使用Process32First 函数获取th32ParentProcessID,它是创建此进程(其父进程)的进程的标识符。

看这个例子。

uses
  Psapi,
  Windows,
  tlhelp32,
  SysUtils;

function GetTheParentProcessFileName(): String;
const
  BufferSize = 4096;
var
  HandleSnapShot  : THandle;
  EntryParentProc : TProcessEntry32;
  CurrentProcessId: DWORD;
  HandleParentProc: THandle;
  ParentProcessId : DWORD;
  ParentProcessFound  : Boolean;
  ParentProcPath      : String;

begin
  ParentProcessFound := False;
  HandleSnapShot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);   //enumerate the process
  if HandleSnapShot <> INVALID_HANDLE_VALUE then
  begin
    EntryParentProc.dwSize := SizeOf(EntryParentProc);
    if Process32First(HandleSnapShot, EntryParentProc) then    //find the first process
    begin
      CurrentProcessId := GetCurrentProcessId(); //get the id of the current process
      repeat
        if EntryParentProc.th32ProcessID = CurrentProcessId then
        begin
          ParentProcessId := EntryParentProc.th32ParentProcessID; //get the id of the parent process
          HandleParentProc := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, ParentProcessId);
          if HandleParentProc <> 0 then
          begin
              ParentProcessFound := True;
              SetLength(ParentProcPath, BufferSize);
              GetModuleFileNameEx(HandleParentProc, 0, PChar(ParentProcPath),BufferSize);
              ParentProcPath := PChar(ParentProcPath);
              CloseHandle(HandleParentProc);
          end;
          break;
        end;
      until not Process32Next(HandleSnapShot, EntryParentProc);
    end;
    CloseHandle(HandleSnapShot);
  end;

  if ParentProcessFound then
    Result := ParentProcPath
  else
    Result := '';
end;

【讨论】:

    【解决方案2】:

    如果该 guid 不是传递给您的实用程序的参数的一部分,我会添加一个您只知道的额外参数(它可以是一个 guid)。立即终止应用程序。

    【讨论】:

    • 我去过那条路。问题是传递给实用程序的参数可以通过主机应用程序的设置或设置屏幕看到。而且我也不能指示主机应用程序在其他地方寻找一些神奇的钥匙。谢谢 Gs!
    【解决方案3】:

    您的问题的快速回答是“嗯,不,您不能阻止应用程序被执行”。如果它是可执行文件,则可以执行。没有办法阻止它。

    而且,如果您无法控制应用程序(正如您的 cmets 所指出的那样),那么 Gs 的出色建议将不起作用,对吧?您无法控制应用程序的功能,也无法控制它对您的特殊命令行的反应。

    所以这确实呈现了一个有趣的情况。

    我看到的唯一方法是完全阻止对 EXE 的访问,或者至少使其难以找到。

    你可以这样做:

    1. 将 EXE 作为资源嵌入到您的主机 EXE 中
    2. 到了运行 EXE 的时候,然后使用 TResourceStream 提取它
    3. 使用 TFileStream 从 TResourceStream 中写出
    4. 执行它
    5. 完成后将其删除。

    不漂亮,但这是我能想到的唯一方法,以防止 EXE 按您的条件运行并且仅按您的条件运行。

    【讨论】:

    • 看来他要问的是是否可以验证启动应用程序的进程的身份,如果是错误的进程则立即终止。这应该是可能的。
    【解决方案4】:

    我们使用了一种相当简单的技术,只需要几行代码。父应用程序和实用程序应用程序使用一些常见的 GUIID 字符串(在代码中)并调用 RegisterWindowMessage 来创建一种“Hello”握手协议。当实用程序首次启动时,它会发布该消息。如果父应用程序正在运行,并且确实启动了该实用程序,它会发布响应消息,该实用程序可以看到并且一切正常。如果没有,该实用程序将超时并退出。

    【讨论】:

    • 必须修改/重写父应用程序才能以这种方式实现它。对吗?
    • 是的。在我编写之前,我没有看到运行该实用程序的第 3 方应用程序。我的错。
    【解决方案5】:

    如果此应用程序仅在主机内部运行,为什么不将应用程序的表单包含在主应用程序中,然后像激活另一个表单一样激活它?

    【讨论】:

    • 我们没有编写这个主机应用程序。只有这种执行另一个应用程序的能力。我只是碰巧知道他们是如何执行的。谢谢蒂姆!
    猜你喜欢
    • 2010-09-05
    • 2013-01-14
    • 2013-08-11
    • 1970-01-01
    • 2020-02-19
    • 2012-01-25
    • 1970-01-01
    • 2011-02-26
    • 2010-12-17
    相关资源
    最近更新 更多