Как я могу заморозить выполнение программы? - PullRequest
7 голосов
/ 31 октября 2010

Скажем, у меня есть программа, которая загружает процессор и / или жесткий диск до такой степени, что практически невозможно что-либо сделать на этом компьютере.Теперь я не хочу убивать эту программу, потому что то, что она делает, полезно (это пакетная работа, которая на самом деле загружает процессор или диск, например, она может заархивировать несколько гигабайт файлов данных), но на короткое время мне нужно сделатьчто-то еще на этом компьютере.Есть ли какой-нибудь способ, которым внешняя программа могла бы на какое-то время заморозить это убийство производительности?

Это похоже на старую опцию DOS для переключения между программами без фактической многозадачности.

Предположим, что гипотетическая программаречь идет о стороннем продукте, для которого у меня нет исходного кода, и нет способа заставить его приостановиться.

Я знаю, что могу изменить класс приоритета программы, например, в TaskManager, но этого недостаточноЯ хочу заморозить его.

Я говорю о Windows XP как об ОС и хотел бы запрограммировать решение с помощью Delphi.У меня есть все права на эту машину, поэтому я мог запускать что-то от имени администратора, заменять файлы и, при необходимости, устанавливать службу.

Ответы [ 4 ]

14 голосов
/ 31 октября 2010

Вы можете заморозить его с помощью Process Explorer : щелкните правой кнопкой мыши на своей программе и выберите Suspend.

Вот пример кода для программного замораживания из http://www.c -plusplus.de / forum / viewtopic-var-p-is-1460293.html , отредактированная и пропущенная проверка ошибок для краткости:

#include <windows.h>

_NtSuspendProcess NtSuspendProcess =
    (_NtSuspendProcess) GetProcAddress( GetModuleHandle( "ntdll" ),
                                        "NtSuspendProcess" ); 
HANDLE ProcessHandle = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pid);
NtSuspendProcess( ProcessHandle );
6 голосов
/ 31 октября 2010

Если вы хотите сделать это программно, вы можете использовать подход, описанный здесь .

Что делает, перечисляет все потоки в процессе и затем приостанавливает их. API SuspendProcess отсутствует, так что это симуляция такого вызова.

Помните, что это может иметь некоторые побочные эффекты. Это зависит от процесса и от того, как оно написано.

Я не знаю другого способа сделать это в мире Win32 / 64 API. Если вы спуститесь на землю ядра и будете использовать API-интерфейсы NT *, у вас есть доступный API-интерфейс NtSuspendProcess. Но это недокументировано, поэтому может меняться с любой версией Windows или даже с любым пакетом обновления (хотя и не очень).

Объявление «NtSuspendProcess» можно найти в портах JEDI Windows API.

4 голосов
/ 31 октября 2010

Вы можете использовать мой ProcessInfo компонент, чтобы приостановить все потоки, принадлежащие процессу.Подход похож на то, что вам объяснил Бегун.Код будет выглядеть примерно так:

var
  Process : TProcessItem;
  AThread: TThreadItem;
begin
  Process := ProcessInfo1.RunningProcesses.FindByName('notepad.exe');
  if Assigned(Process) then
  begin
    for AThread in Process.Threads do
      AThread.SuspendThread;
  end;
end;

Вы можете скачать исходный код ProcessInfo здесь

2 голосов
/ 31 октября 2010
function OpenThread(dwDesiredAccess: DWORD; InheritHandle: Boolean; dwThreadID: DWORD): THandle; stdcall; external 'kernel32.dll';

function ResumeProcess(PID: DWORD):Boolean;
var
  tid, snap: THandle;
  TE32: TThreadEntry32;
begin
  Result := False;
  snap := CreateToolHelp32SnapShot(TH32CS_SNAPTHREAD, 0);
  TE32.dwSize := SizeOf(TThreadEntry32);
  Thread32First(snap, TE32);
  repeat
    if TE32.th32OwnerProcessID = PID then begin
      tid := OpenThread($0002, FALSE, TE32.th32ThreadID);
      ResumeThread(tid);
      Result := TRUE;
      CloseHandle(tid);
    end;
  until Thread32Next(snap, TE32) = false;
  CloseHandle(snap);
end;

function SuspendProcess(PID: DWORD): Boolean;
var
  tid, snap: THandle;
  TE32: TThreadEntry32;
begin
  Result := False;
  snap := CreateToolHelp32SnapShot(TH32CS_SNAPTHREAD, 0);
  TE32.dwSize := SizeOf(TThreadEntry32);
  Thread32First(snap, TE32);
  repeat
    if TE32.th32OwnerProcessID = PID then begin
      tid := OpenThread($0002, FALSE, TE32.th32ThreadID);
      SuspendThread(tid);
      Result := TRUE;
      CloseHandle(tid);
    end;
  until Thread32Next(snap, TE32) = false;
  CloseHandle(snap);
end;

Надеюсь, это поможет

...