11

Say I have got a program that hogs the processor and/or hard disk to the point that it makes it nearly impossible to do anything else on that computer. Now I don't want to kill that program because what it does is useful (it's a batch job that really is that CPU or disk heavy, e.g. it could ZIP a few gigabytes of data files) but for a short time I need to do something else on that computer. Is there any way an external program could do to freeze that performance killer for a while?

It's like the old DOS option to switch between programs without actually having multitasking.

Assume that the hypothetical program in question is a 3rd party product for which I don't have the source code and there is no way to tell it to pause.

I know I can change the program's priority class e.g. in TaskManager but that's not enough, I want to freeze it.

I am talking about Windows XP as the OS and would like to program a solution with Delphi. I have got all rights on the machine, so I could start something as administrator, replace files and I could also install a service if that is necessary.

dummzeuch
  • 10,975
  • 4
  • 51
  • 158
  • 2
    For an alternative solution using using DebugActiveProcess: http://stackoverflow.com/questions/11010165/ho-to-suspend-resume-a-process-in-windows/11010508#11010508 – Adriano Repetti Jun 13 '12 at 16:33

4 Answers4

15

You can freeze it with Process Explorer: Right-click on your program and select Suspend.

Here is some sample code for programmatic freezing from http://www.c-plusplus.de/forum/viewtopic-var-p-is-1460293.html, edited and omitted error checking for brevity:

#include <windows.h>

_NtSuspendProcess NtSuspendProcess =
    (_NtSuspendProcess) GetProcAddress( GetModuleHandle( "ntdll" ),
                                        "NtSuspendProcess" ); 
HANDLE ProcessHandle = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pid);
NtSuspendProcess( ProcessHandle );
Peter G.
  • 14,786
  • 7
  • 57
  • 75
  • 1
    Ah yes, but what API call is it using? SuspendThread on all of the process' threads? http://msdn.microsoft.com/en-us/library/ms686345(v=VS.85).aspx – Stijn Sanders Oct 31 '10 at 10:08
  • 3
    Knowing Russinovich and his knowledge of the Kernel it probably uses NtSuspendProcess directly. – Runner Oct 31 '10 at 10:12
  • Here the text in English http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx – Dr. belisarius Oct 31 '10 at 10:33
  • 1
    @Runner Thanks, added some sample code for NtSuspendProcess, @belisarius Thanks, edited my link to point to English version. – Peter G. Oct 31 '10 at 10:53
6

If you want to do it programatically you can use the approach described here.

What is does, is enumerating all the threads in a process and then suspending them. There is no SuspendProcess API, so this is a simulation of such a call.

Beware that this can potentionally have some bad side effects. It depend on the process and how it is written.

I don't know of any other way to do it in the Win32/64 API world. If you go lower to the kernel land and use the NT* APIs you have "NtSuspendProcess" API available. But this is undocumented so it can change with any version of windows or even with any service pack (not very likely though).

The declaration of "NtSuspendProcess" can be found in the JEDI ports of the windows APIs.

Runner
  • 6,073
  • 26
  • 38
4

You can use my ProcessInfo component to suspend all threads belonging to the process. The approach is similar to what Runner explained to you. The code would be something like this:

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;

You can download source code of ProcessInfo form here

vcldeveloper
  • 7,399
  • 2
  • 33
  • 39
  • I accept your answer even though the others are also correct and contain more information on the specifics, but I am lazy, so I like using a component. – dummzeuch Nov 01 '10 at 08:30
  • @vcldeveloper, How is this different from resmon http://stackoverflow.com/a/21649539/632951 ? – Pacerier Jan 29 '17 at 12:13
2
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;

Hope this helps

dummzeuch
  • 10,975
  • 4
  • 51
  • 158
opc0de
  • 11,557
  • 14
  • 94
  • 187