像PsSuspend那样暂停/恢复进程

men*_*raz 11 delphi winapi 32-bit process windows-7

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

我考虑过类似的帖子如何在Windows下暂停/恢复任何外部进程?但是使用C++/Python首选项,但截至发布时尚未接受答案.


我的问题:

我感兴趣的所提供的功能在Delphi一个可能的实现PsSuspend通过标记Russinovich的Windows Sysinternals的.

行情:

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

谢谢.


编辑:

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

TLa*_*ama 10

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

更新

SuspendProcessResumeProcess现在的包装从下面的代码是功能和回报,如果成功True,否则假.

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;
Run Code Online (Sandbox Code Playgroud)

  • 这是无证功能的乐趣.无论如何,`OpenProcess`返回一个进程句柄而不是一个模块句柄FWIW. (4认同)
  • 这是[如何检查线程/进程是否被暂停](http://vtopan.wordpress.com/2009/04/15/how-to-find-out-if-a-threadprocess-is-suspended-get-线程状态/) (3认同)
  • 这里有一些[代码示例](http://programmersforum.ru/showthread.php?t=5343)(还显示了如何暂停每个线程).从内部'PsSuspend`程序开始,我相信它也使用这些API.还有一件事,以某种方式得到当前状态会很好,就像在Process Explorer中一样. (2认同)
  • 我不相信使用`PROCESS_ALL_ACCESS`的代码.指定操作所需的最小访问权限始终是一个好主意.也许您需要使用`SeDebugPrivilege`设置调用进程,这应该使用标准用户权限进行测试. (2认同)
  • @TLama:找到这个网站[未记载的函数](http://undocumented.ntinternals.net/).似乎很有趣. (2认同)

Dav*_*nan 5

SuspendProcessWindows中没有API调用.所以你需要做的是:

  1. 枚举进程中的所有线程.有关示例代码,请参阅RRUZ的答案.
  2. 调用SuspendThread每个线程.
  3. 为了实现程序的恢复部分,请调用ResumeThread每个线程.

  • 马克在写完PsSuspend后加入了MS.同样,它可以很好地使用未记录的API.他还在加入MS之前编写了Windows Internals,因此内部或外部几乎没有什么区别.我认为配置文件模式下的依赖walker会告诉你使用了什么API. (2认同)

小智 5

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

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

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