Page 1 of 1

How to suspend a process?

Posted: Thu Feb 06, 2014 6:51 pm
by ostapas
Good day,
need to suspend/resume a process. To my astonishment, could not find any PB examples, but found these 2 functions on AutoIt forums:

Code: Select all

Func ProcessSuspend($Process_PID)
	$ai_Handle = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', 0x1f0fff, 'int', False, 'int', $Process_PID)
	$i_sucess = DllCall("ntdll.dll", "int", "NtSuspendProcess", "int", $ai_Handle[0])
	DllCall('kernel32.dll', 'ptr', 'CloseHandle', 'ptr', $ai_Handle)
EndFunc   

Func ProcessResume($Process_PID)
	$ai_Handle = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', 0x1f0fff, 'int', False, 'int', $Process_PID)
	$i_sucess = DllCall("ntdll.dll", "int", "NtResumeProcess", "int", $ai_Handle[0])
	DllCall('kernel32.dll', 'ptr', 'CloseHandle', 'ptr', $ai_Handle)
EndFunc   
Maybe someone who has winapi knowledge and a spare minute could help to transform this to PB? :)

Re: How to suspend a process?

Posted: Thu Feb 06, 2014 8:16 pm
by JHPJHP
Try the following:
- can also be done with threads: http://stackoverflow.com/questions/1101 ... in-windows
- may not need [ AdjustCurrentProcessPrivilege ], but I included it just in case

Windows Services & Other Stuff\Other_Stuff\ProcessStuff\SuspendProcess.pb

Re: How to suspend a process?

Posted: Thu Feb 06, 2014 9:03 pm
by ostapas
Working fine, many thanks!

Re: How to suspend a process?

Posted: Fri Feb 07, 2014 2:59 am
by PB
> may not need [ AdjustCurrentProcessPrivilege ]

I don't think it does. I run under a Limited account (not Admin) and your
code paused and resumed every process that I tested it with. Good job.

Re: How to suspend a process?

Posted: Fri Feb 07, 2014 9:25 am
by ostapas
JHPJHP, thanks again for arranging the code into procedures

Re: How to suspend a process?

Posted: Wed Nov 19, 2014 12:40 pm
by smacker
NtSuspendProcess is an undocumented function isn't it? Undocumented functions are not supported in the API, and may suddenly vanish or be changed in some way by later updates/service packs or versions of windows, so I'm a little shy about using such if I want my stuff to keep working in later versions of Windows or after updates/service packs in case something does happen to NtSuspendProcess.

This is something I used in Windows 7 64 bit (don't know about Win 7 32 bit version) for my purposes to pause (suspend) the thread of another process via its PID that did not belong to my own process which is the same thing as pausing/suspending the process, you could also do your own process as well, never tried it in Windows 8 so don't know about there but it worked in Windows 7 64 bit, the not so pretty version is this:

Code: Select all

Structure thread32 
size.l 
use.l 
idth.l 
parentid.l 
base.l 
delta.l 
flags.l 
EndStructure 

OpenLibrary(0,"kernel32.dll") 

Procedure pause(pid) 

thread.thread32 

snap = CallFunction(0, "CreateToolhelp32Snapshot",4,0) 
If snap 

thread\size=SizeOf(thread32) 
CallFunction(0,"Thread32First",snap,@thread) 

If thread\parentid=pid 
  h=CallFunction(0,"OpenThread",2,0,thread\idth) 
  SuspendThread_(h) 
  CloseHandle_(h) 
EndIf 

While CallFunction(0,"Thread32Next",snap,@thread) 

If thread\parentid=pid 
  h=CallFunction(0,"OpenThread",2,0,thread\idth) 
  SuspendThread_(h) 
  CloseHandle_(h) 
EndIf 

Wend 

EndIf 

EndProcedure

Procedure resume(pid) 

thread.thread32 

snap = CallFunction (0, "CreateToolhelp32Snapshot",4,0) 
If snap 

thread\size=SizeOf(thread32) 
CallFunction(0,"Thread32First",snap,@thread) 

If thread\parentid=pid 
  h=CallFunction(0,"OpenThread",2,0,thread\idth) 
  ResumeThread_(h) 
  CloseHandle_(h) 
EndIf 

While CallFunction(0,"Thread32Next",snap,@thread) 

If thread\parentid=pid 
  h=CallFunction(0,"OpenThread",2,0,thread\idth) 
  ResumeThread_(h) 
  CloseHandle_(h) 
EndIf 

Wend 

EndIf 
EndProcedure

Can't find the pretty version right now but I'm sure you could restructure the code some to pretty it up a little.

Re: How to suspend a process?

Posted: Wed Nov 19, 2014 12:43 pm
by ostapas
Smacker, many thanks!

Re: How to suspend a process?

Posted: Wed Nov 19, 2014 2:47 pm
by Thunder93
smacker raises some valid points.

Code: Select all

Prototype protoOpenThread(dwDesiredAccess.l, bInheritHandle.b, dwThreadId.l)
Global OpenThread.protoOpenThread


Procedure ResumeProcess(ProcessID.l)
  Define.l hSnap, cThr, IsRes
  ThrHandle.i
  
  LibKernel32 = OpenLibrary(#PB_Any,"Kernel32.dll")
  If Not LibKernel32 : ProcedureReturn 0 : EndIf 
  
  OpenThread = GetFunction(LibKernel32, "OpenThread")
  
  Thread.THREADENTRY32
  cThr = GetCurrentThreadId_()  
  
  hSnap = CreateToolhelp32Snapshot_(#TH32CS_SNAPTHREAD, 0)
  If hSnap <> #INVALID_HANDLE_VALUE
    Thread\dwSize = SizeOf(THREADENTRY32)
    If Thread32First_(hSnap, Thread)
      Repeat
        If (Thread\th32ThreadID <> cThr) And (Thread\th32OwnerProcessID = ProcessID)          
          ThrHandle = OpenThread(#THREAD_SUSPEND_RESUME, 0, Thread\th32ThreadID)
          
          If ThrHandle = 0 : Break : EndIf
          IsRes = ResumeThread_(ThrHandle)
          CloseHandle_(ThrHandle) 
        EndIf
        
      Until Not Thread32Next_(hSnap, Thread)      
      CloseHandle_(hSnap)
      CloseLibrary(LibKernel32)
      
      If IsRes > 0 : ProcedureReturn 1 : EndIf      
    EndIf
  EndIf
EndProcedure

Procedure SuspendProcess(PID.l)
  Define.l hSnap, IsSus
  ThrHandle.i  
  
  LibKernel32 = OpenLibrary(#PB_Any,"Kernel32.dll")
  If Not LibKernel32 : ProcedureReturn 0 : EndIf 
  
  OpenThread = GetFunction(LibKernel32, "OpenThread")  
  
  THR32.THREADENTRY32  
  
  hSnap = CreateToolhelp32Snapshot_(#TH32CS_SNAPTHREAD, 0)
  If hSnap <> #INVALID_HANDLE_VALUE
    THR32\dwSize = SizeOf(THR32)
    Thread32First_(hSnap, THR32)
    Repeat
      If THR32\th32OwnerProcessID = PID
        LibKernel32 = OpenLibrary(#PB_Any,"Kernel32.dll")
        
        ThrHandle = OpenThread(#THREAD_SUSPEND_RESUME, #False, THR32\th32ThreadID)      
        If ThrHandle <> #INVALID_HANDLE_VALUE
          IsSus = SuspendThread_(ThrHandle)
          CloseHandle_(ThrHandle)
        EndIf
      EndIf
    Until Thread32Next_(hSnap, THR32) = #False     
    CloseHandle_(hSnap)
    CloseLibrary(LibKernel32)
    
    If IsSus <> #INVALID_HANDLE_VALUE : ProcedureReturn 1 : EndIf
  EndIf
EndProcedure

Re: How to suspend a process?

Posted: Thu Mar 18, 2021 7:13 pm
by BarryG
Apparently this pausing/resuming with the techniques above is bad/wrong because it doesn't pause all threads of a process, which is required. The answer is to use DebugActiveProcess_(pid) to pause and DebugActiveProcessStop_(pid) to resume, because this is how debuggers do it to ensure all threads of a PID are suspended. However, DebugActiveProcessStop_() doesn't exist in PureBasic. How can we add it? I tried this, but it doesn't work:

Code: Select all

Procedure DebugActiveProcessStop(pid)
  If OpenLibrary(0,"kernel32.dll")
    CallFunction(0,"DebugActiveProcessStop",0,0,pid)
    CloseLibrary(0)
  EndIf
EndProcedure

pid=11392 ; Change to an observable running process ID.
DebugActiveProcess_(pid)
Sleep_(1000)
DebugActiveProcessStop(pid)

Re: How to suspend a process?

Posted: Thu Mar 18, 2021 11:10 pm
by breeze4me
BarryG wrote:Apparently this pausing/resuming with the techniques above is bad/wrong because it doesn't pause all threads of a process, which is required. The answer is to use DebugActiveProcess_(pid) to pause and DebugActiveProcessStop_(pid) to resume, because this is how debuggers do it to ensure all threads of a PID are suspended. However, DebugActiveProcessStop_() doesn't exist in PureBasic. How can we add it? I tried this, but it doesn't work:

Code: Select all

Procedure DebugActiveProcessStop(pid)
  If OpenLibrary(0,"kernel32.dll")
    CallFunction(0,"DebugActiveProcessStop",0,0,pid)
    CloseLibrary(0)
  EndIf
EndProcedure

pid=11392 ; Change to an observable running process ID.
DebugActiveProcess_(pid)
Sleep_(1000)
DebugActiveProcessStop(pid)
1. The parameters are wrong.
2. It does not seem to apply to 64-bit processes if it is compiled with PB x86. Compile it with PB x64 and check it out again.

Code: Select all

CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
  CompilerError "Use PB x64."
CompilerEndIf

Procedure DebugActiveProcessStop(pid)
  If OpenLibrary(0,"kernel32.dll")
    CallFunction(0,"DebugActiveProcessStop",pid)
    CloseLibrary(0)
  EndIf
EndProcedure


pid=11392 ; Change to an observable running process ID.
r = DebugActiveProcess_(pid)
If r
  Sleep_(1000)
  Debug DebugActiveProcessStop(pid)
EndIf

Re: How to suspend a process?

Posted: Thu Mar 18, 2021 11:25 pm
by BarryG
Thanks, breeze4me. And you're right: compiling as 32-bit works great for 32-bit processes, but can't pause 64-bit.