从主应用程序中杀死子进程

时间:2010-01-20 16:23:36

标签: multithreading delphi winapi

我有一个在后台运行python脚本的Delphi服务器(它们的运行类似于“python Sync.py **params**”)。

此脚本可以执行诸如连接到外部服务器,打开ssh连接以及可以挂起的可怕内容之类的操作。

我需要检测它们是否挂起并杀死它。此外,如果服务器已关闭,并且也想要终止进程(如果没有,则Delphi服务器挂起,从桌面消失但在后台不可见。如果再次执行服务器,这会导致问题。)

首先尝试不工作。该进程被杀死,但如果我关闭应用程序,则服务器挂起。

所以问题是,是否存在更可靠/更好的方法来杀死子进程。

现在,我保存他们的Handle和他们的GetTickCount,如下所示:“handle = tickcount”,然后每4秒运行一次TTimer并查看进程是否超时:

procedure TfrmMain.CheckProcess(Sender: TObject);
var
  i: Integer;
  Fecha:TDateTime;
  start, stop, elapsed,Handle : cardinal;
begin
  stop := GetTickCount;

  for i := (FProcesos.Count - 1) downto 0 do
  begin
      start := StrToInt( FProcesos.ValueFromIndex[i] );
      elapsed := stop - start; //milliseconds
      //Esta muerto el proceso??
      if ((elapsed>TIMEOUT_PROCESS) or (FTimer.Enabled=False)) then
      begin
        Handle := StrToInt( FProcesos.Names[i] );

        TerminateProcess(Handle,0);
        CloseHandle( Handle );

        FProcesos.Delete( i );
        LogMsg('A process timed out!',msgError);
      end;
  end;//for
end;

2 个答案:

答案 0 :(得分:0)

我不明白你是如何检查一个过程是否没有响应。如果您的子进程具有GUI,则可以使用SendMessageTimeOut API函数向属于该进程的其中一个窗口发送消息,并检查该消息是否在指定时间内由其处理。

下面是一个示例代码,它使用我的TProcessInfo列出当前线程的所有子进程,并终止任何没有响应的子进程 - 请注意,因为我无法理解您的检测方法没有响应的进程,IsProcessUnResponsive函数没有在我的代码中实现,并留给你:

function IsProcessUnResponsive(const ProcessID: Cardinal): Boolean;
begin
  //Use your own technique for determining if a process is not responsive.
end;

procedure TerminateUnResponsiveProcesses;
var
  Process: TProcessItem;
  ProcessInfo : TProcessInfo;
begin
  ProcessInfo := TProcessInfo.Create(nil);
  try
    for Process in ProcessInfo.RunningProcesses do
    begin
      if Process.ParentProcessID = GetCurrentProcessId then
        if IsProcessUnResponsive(Process.ProcessID) then
          Process.TerminateProcess;    
    end;
  finally
    ProcessInfo.Free;
  end;
end;

答案 1 :(得分:0)

调用TerminateProcess是杀死进程的唯一可靠方法。

有更多优雅的方式,但要使用它们,您需要了解过程如何被告知关闭。 GUI进程通常希望关闭它们的主窗口,因此您需要确定它们是哪些窗口,然后向它们发送wm_Close消息。批处理模式控制台程序可能希望您按Ctrl + C;交互式控制台程序可能有一个你应该键入的特殊命令。

并且所有这些都假定该过程仍在响应输入。如果进程挂起,它可能永远不会看到“优雅”命令,因此TerminateProcess强制终止是唯一剩下的选项。

如果我是你,我会在错误消息中避免使用术语 zombie process 。你正在处理的不是僵尸。僵尸是终止的进程,但其他进程仍有一个打开的句柄。您正在做的是检测运行时间过长且超时的进程。它们不一定是挂起的流程,只是占用时间超过规定时间的流程。所以只需在错误消息中说 :“进程已超时”。 (如果你能记录哪个处理的一些有意义的指示,那就更好了。)