像PsSuspend那样暂停/恢复进程

时间:2012-04-14 11:04:04

标签: delphi winapi windows-7 process 32-bit

我希望这篇文章不是重复的。让我解释一下:

我已经考虑了类似的帖子How to pause / resume any external process under Windows?但是使用了C ++ / Python首选项,但截至发布时尚未接受答案。


我的问题:

我感兴趣的是在Delphi中可能实现了由{em> Windows Sysinternals 的 Mark Russinovich 提供的PsSuspend功能。

行情:

  

PsSuspend允许您暂停本地或远程系统上的进程,   这在流程消耗资源的情况下是理想的   (例如,网络,CPU或磁盘)您希望允许不同的进程   使用。而不是杀死消耗资源的进程,   暂停允许您稍后让它继续运行   时间点。

谢谢。


修改

部分实现可以。远程功能可以被删除。

4 个答案:

答案 0 :(得分:10)

您可以尝试使用以下代码。它使用未记录的函数NtSuspendProcessNtResumeProcess。我已经在Delphi 2009中构建的32位应用程序的Windows 7 64位上尝试过它,它对我有用。请注意,这些函数未记录,因此可以从Windows的未来版本中删除。

更新

以下代码中的SuspendProcessResumeProcess包装器现在是函数,如果成功则返回True,否则返回False。

type
  NTSTATUS = LongInt;
  TProcFunction = function(ProcHandle: THandle): NTSTATUS; stdcall;

const
  STATUS_SUCCESS = $00000000;
  PROCESS_SUSPEND_RESUME = $0800;

function SuspendProcess(const PID: DWORD): Boolean;
var
  LibHandle: THandle;
  ProcHandle: THandle;
  NtSuspendProcess: TProcFunction;
begin
  Result := False;
  LibHandle := SafeLoadLibrary('ntdll.dll');
  if LibHandle <> 0 then
  try
    @NtSuspendProcess := GetProcAddress(LibHandle, 'NtSuspendProcess');
    if @NtSuspendProcess <> nil then
    begin
      ProcHandle := OpenProcess(PROCESS_SUSPEND_RESUME, False, PID);
      if ProcHandle <> 0 then
      try
        Result := NtSuspendProcess(ProcHandle) = STATUS_SUCCESS;
      finally
        CloseHandle(ProcHandle);
      end;
    end;
  finally
    FreeLibrary(LibHandle);
  end;
end;

function ResumeProcess(const PID: DWORD): Boolean;
var
  LibHandle: THandle;
  ProcHandle: THandle;
  NtResumeProcess: TProcFunction;
begin
  Result := False;
  LibHandle := SafeLoadLibrary('ntdll.dll');
  if LibHandle <> 0 then
  try
    @NtResumeProcess := GetProcAddress(LibHandle, 'NtResumeProcess');
    if @NtResumeProcess <> nil then
    begin
      ProcHandle := OpenProcess(PROCESS_SUSPEND_RESUME, False, PID);
      if ProcHandle <> 0 then
      try
        Result := NtResumeProcess(ProcHandle) = STATUS_SUCCESS;
      finally
        CloseHandle(ProcHandle);
      end;
    end;
  finally
    FreeLibrary(LibHandle);
  end;
end;

答案 1 :(得分:5)

Windows中没有SuspendProcess API调用。所以你需要做的是:

  1. 枚举流程中的所有主题。有关示例代码,请参阅RRUZ's answer
  2. 为每个线程调用SuspendThread
  3. 为了实现程序的简历部分,请为每个线程调用ResumeThread

答案 2 :(得分:4)

“暂停所有线程”实现存在竞争条件 - 如果您尝试挂起的程序在创建快照的时间和完成挂起的时间之间创建一个或多个线程,会发生什么?

您可以循环,获取另一个快照并暂停任何未挂起的线程,只有在您找不到时才退出。

未记录的功能避免了这个问题。

答案 3 :(得分:1)

我刚刚找到以下代码段here(作者:steve10120)。

我认为它们是有价值的,我也不能将它们作为我自己问题的替代答案发布。


恢复流程:

function ResumeProcess(ProcessID: DWORD): Boolean;
 var
   Snapshot,cThr: DWORD;
   ThrHandle: THandle;
   Thread:TThreadEntry32;
 begin
   Result := False;
   cThr := GetCurrentThreadId;
   Snapshot := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
   if Snapshot <> INVALID_HANDLE_VALUE then
    begin
     Thread.dwSize := SizeOf(TThreadEntry32);
     if Thread32First(Snapshot, Thread) then
      repeat
       if (Thread.th32ThreadID <> cThr) and (Thread.th32OwnerProcessID = ProcessID) then
        begin
         ThrHandle := OpenThread(THREAD_ALL_ACCESS, false, Thread.th32ThreadID);
         if ThrHandle = 0 then Exit;
         ResumeThread(ThrHandle);
         CloseHandle(ThrHandle);
        end;
      until not Thread32Next(Snapshot, Thread);
      Result := CloseHandle(Snapshot);
     end;
 end;

暂停流程:

function SuspendProcess(PID:DWORD):Boolean;
 var
 hSnap:  THandle;
 THR32:  THREADENTRY32;
 hOpen:  THandle;
 begin
   Result := FALSE;
   hSnap := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
   if hSnap <> INVALID_HANDLE_VALUE then
   begin
     THR32.dwSize := SizeOf(THR32);
     Thread32First(hSnap, THR32);
     repeat
       if THR32.th32OwnerProcessID = PID then
       begin
         hOpen := OpenThread($0002, FALSE, THR32.th32ThreadID);
         if hOpen <> INVALID_HANDLE_VALUE then
         begin
           Result := TRUE;
           SuspendThread(hOpen);
           CloseHandle(hOpen);
         end;
       end;
     until Thread32Next(hSnap, THR32) = FALSE;
     CloseHandle(hSnap);
   end;
 end;

<强>声明:

我根本没有测试过它们。请享受,不要忘记反馈。