如何在 Windows 中挂起/恢复进程?

在 Unix 中,我们可以暂时中止一个进程的执行,并使用信号 SIGSTOPSIGCONT恢复它。如何在没有编程的情况下挂起 Windows 中的单线程进程?

152513 次浏览

You can't do it from the command line, you have to write some code (I assume you're not just looking for an utility otherwise Super User may be a better place to ask). I also assume your application has all the required permissions to do it (examples are without any error checking).

Hard Way

First get all the threads of a given process then call the SuspendThread function to stop each one (and ResumeThread to resume). It works but some applications may crash or hung because a thread may be stopped in any point and the order of suspend/resume is unpredictable (for example this may cause a dead lock). For a single threaded application this may not be an issue.

void suspend(DWORD processId)
{
HANDLE hThreadSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);


THREADENTRY32 threadEntry;
threadEntry.dwSize = sizeof(THREADENTRY32);


Thread32First(hThreadSnapshot, &threadEntry);


do
{
if (threadEntry.th32OwnerProcessID == processId)
{
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE,
threadEntry.th32ThreadID);
            

SuspendThread(hThread);
CloseHandle(hThread);
}
} while (Thread32Next(hThreadSnapshot, &threadEntry));


CloseHandle(hThreadSnapshot);
}

Please note that this function is even too much naive, to resume threads you should skip threads that was suspended and it's easy to cause a dead-lock because of suspend/resume order. For single threaded applications it's prolix but it works.

Undocumented way

Starting from Windows XP there is the NtSuspendProcess but it's undocumented. Read this post (or this article) for a code example (reference for undocumented functions: news://comp.os.ms-windows.programmer.win32).

typedef LONG (NTAPI *NtSuspendProcess)(IN HANDLE ProcessHandle);


void suspend(DWORD processId)
{
HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId));


NtSuspendProcess pfnNtSuspendProcess = (NtSuspendProcess)GetProcAddress(
GetModuleHandle("ntdll"), "NtSuspendProcess");


pfnNtSuspendProcess(processHandle);
CloseHandle(processHandle);
}

"Debugger" Way

To suspend a program is what usually a debugger does, to do it you can use the DebugActiveProcess function. It'll suspend the process execution (with all threads all together). To resume you may use DebugActiveProcessStop.

This function lets you stop a process (given its Process ID), syntax is very simple: just pass the ID of the process you want to stop et-voila. If you'll make a command line application you'll need to keep its instance running to keep the process suspended (or it'll be terminated). See the Remarks section on MSDN for details.

void suspend(DWORD processId)
{
DebugActiveProcess(processId);
}

From Command Line

As I said Windows command line has not any utility to do that but you can invoke a Windows API function from PowerShell. First install Invoke-WindowsApi script then you can write this:

Invoke-WindowsApi "kernel32" ([bool]) "DebugActiveProcess" @([int]) @(process_id_here)

Of course if you need it often you can make an alias for that.

I use (a very old) process explorer from SysInternals (procexp.exe). It is a replacement / addition to the standard Task manager, you can suspend a process from there.

Edit: Microsoft has bought over SysInternals, url: procExp.exe

Other than that you can set the process priority to low so that it does not get in the way of other processes, but this will not suspend the process.

Well, Process Explorer has a suspend option. You can right click a process in the process column and select suspend. Once you are ready to resume it again right click and this time select resume. Process Explorer can be obtained from here:

http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx

PsSuspend command line utility from SysInternals suite. It suspends / resumes a process by its id.

Without any external tool you can simply accomplish this on Windows 7, 8 or 10, by opening up the Resource monitor and on the CPU or Overview tab right clicking on the process and selecting Suspend Process. The Resource monitor can be started from the Performance tab of the Task manager.

#pragma comment(lib,"ntdll.lib")
EXTERN_C NTSTATUS NTAPI NtSuspendProcess(IN HANDLE ProcessHandle);


void SuspendSelf(){
NtSuspendProcess(GetCurrentProcess());
}

ntdll contains the exported function NtSuspendProcess, pass the handle to a process to do the trick.

PsSuspend, as mentioned by Vadzim, even suspends/resumes a process by its name, not only by pid.

I use both PsSuspend and PsList (another tool from the PsTools suite) in a simple toggle script for the OneDrive process: if I need more bandwidth, I suspend the OneDrive sync, afterwards I resume the process by issuing the same mini script:

PsList -d onedrive|find/i "suspend" && PsSuspend -r onedrive || PsSuspend onedrive

PsSuspend command line utility from SysInternals suite. It suspends / resumes a process by its id.

As of 2022 there is now a simple to use open source tray icon tool available to quickly suspend and resume apps: Eco Mode App Switch