如何在Windows中暂停/恢复进程?


Answers:


102

您不能从命令行执行此操作,而必须编写一些代码(我想您不只是在寻找实用程序,否则超级用户可能是一个更好的地方)。我还假设您的应用程序具有执行此操作所需的所有权限(示例中未进行任何错误检查)。

艰辛的道路

首先获取给定进程的所有线程,然后调用该SuspendThread函数以停止每个线程(并ResumeThread恢复)。它可以工作,但是某些应用程序可能会崩溃或挂起,因为线程可能随时停止,并且挂起/恢复的顺序是不可预测的(例如,这可能导致死锁)。对于单线程应用程序,这可能不是问题。

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);
}

请注意,此功能过于幼稚,要恢复线程,您应该跳过已暂停的线程,由于暂停/恢复顺序,很容易造成死锁。对于单线程应用程序,它是prolix,但是可以工作。

无证方式

从Windows XP开始,有,NtSuspendProcess但未记载。阅读此文章以获取代码示例(未记录功能的参考: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);
}

“调试器”方式

挂起程序通常是调试器执行的操作,您可以使用该DebugActiveProcess函数。它将暂停进程执行(所有线程都在一起)。要恢复,您可以使用DebugActiveProcessStop

此功能使您可以停止一个进程(给定其进程ID),语法非常简单:只需传递您要停止et-voila的进程的ID。如果要创建命令行应用程序,则需要保持其实例运行以保持进程挂起(否则它将被终止)。有关详细信息,请参见MSDN上的“备注”部分。

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

从命令行

正如我所说的,Windows命令行没有任何实用程序可以执行此操作,但是您可以从PowerShell中调用Windows API函数。首先安装Invoke-WindowsApi脚本,然后可以编写以下代码:

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

当然,如果您经常需要它,可以alias为此做一个。


您说“安装Invoke-WindowsApi”是什么意思?
MemphiZ 2014年

@MemphiZ这是一个小的小命令(Invoke-WindowsApi),让你调用一个的Windows APIPASCAL调用约定,通常WINAPI)C函数。它不是PowerShell的一部分,因此必须单独下载和安装
Adriano Repetti 2014年

2
您的很好答案的第一句话是错误的。是的,您可以从命令行进行操作!从www.sysinternals.com下载PsSuspend。这个小工具甚至可以挂起在另一台计算机上运行的进程。technet.microsoft.com/zh-CN/sysinternals/bb897540.aspx
Elmue,2015年

1
这些进程是否在任务管理器的“状态”列中显示为“已暂停”?
CMCDragonkai '17

2
@Pacerier-程序员有时会无意中在具有多个线程的程序中创建“竞赛条件”。竞争条件意味着程序在某种程度上取决于程序的两个独立执行部分执行工作的顺序。就像您知道您的朋友总是比您更快地完成某项任务一样,因此您依赖它。但是,如果您的朋友因某种原因而受阻,那么突然不再是如此。程序很精致。您可以调整,也许。程序不能。
全天

83

无需任何外部工具,您只需在Windows 7或8上打开资源监视器,然后在CPU或Overview选项卡上右键单击该进程,然后选择Suspend Process即可完成此操作。可以从任务管理器的“性能”选项卡启动资源监视器。


@ Sigroad,resmon.exe是否与Adriano的回答相同?
佩里耶

@Pacerier不幸的是,我不知道resmon.exe在内部如何工作。
Sigroad '17

1
我第一次以某种方式错过了它,但是现在当右键单击Sysinternals的Process Explorer中的流程时,我也看到了该选项procexp.exe
Pysis

41

我使用了来自SysInternals(procexp.exe)的(非常古老的)进程浏览器。它是标准任务管理器的替代/补充,您可以从那里暂停一个进程。

编辑:微软已经购买了SysInternals,URL:procExp.exe

除此之外,您可以将进程优先级设置为低,这样它就不会妨碍其他进程,但这不会挂起该进程。


1
这几乎完美地回答了这个问题,不知道为什么它没有得到更多的支持。
劳尔

您可以暂停进程,让计算机进入睡眠状态,然后在唤醒后重新启动该进程吗?我有一个实用程序,需要运行几天(总计),但是我不想将计算机保持24/7的状态。
posfan12

@ posfan12为什么不只是让计算机进入睡眠状态?作为一个不相关的例子,当我的窗口之一是最小化的,它已经有了约24 4低的背景优先4. shivesh网速慢的回答似乎涵盖在同类软件更好的选择。
Pysis

“为什么不让计算机进入睡眠状态?” 因为我不希望整个过程完全中断。
posfan12



5

正如Vadzim提到的那样PsSuspend甚至通过其名称(不仅是pid)暂停/恢复进程。

我在用于OneDrive进程的简单切换脚本中同时使用了PsSuspend和PsList(PsTools套件中的另一个工具):如果需要更多带宽,则挂起OneDrive同步,然后通过发布相同的迷你脚本来恢复该过程:

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

套件中的PsSuspend命令行实用程序SysInternals。它通过其ID挂起/恢复进程。


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

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

ntdll包含导出的函数NtSuspendProcess,将句柄传递给进程即可。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.