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

Mic*_*ael 70 windows signals process

在Unix中,我们可以临时暂停进程执行并使用信号SIGSTOP和恢复它SIGCONT.如何在没有编程的情况下暂停Windows中的单线程进程?

Adr*_*tti 92

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

艰辛的道路

首先获取给定进程的所有线程,然后调用该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);
}
Run Code Online (Sandbox Code Playgroud)

请注意,这个函数甚至太天真了,要恢复线程,你应该跳过被挂起的线程,并且由于暂停/恢复顺序很容易导致死锁.对于单线程应用程序来说,它是冗长但它可以工作.

无证的方式

从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);
}
Run Code Online (Sandbox Code Playgroud)

"调试器"的方式

暂停程序通常是调试器的功能,为此可以使用该DebugActiveProcess功能.它将暂停进程执行(所有线程都在一起).要恢复,你可以使用DebugActiveProcessStop.

此函数允许您停止进程(给定其进程ID),语法非常简单:只需传递要停止的进程的ID et-voila.如果您要创建命令行应用程序,则需要保持其实例运行以保持进程暂停(或者它将被终止).有关详细信息,请参阅MSDN上的" 备注"部分.

void suspend(DWORD processId)
{
    DebugActiveProcess(processId);
}
Run Code Online (Sandbox Code Playgroud)

从命令行

正如我所说,Windows命令行没有任何实用程序,但您可以从PowerShell调用Windows API函数.首先安装Invoke-WindowsApi脚本然后你可以这样写:

Invoke-WindowsApi "kernel32" ([bool]) "DebugActiveProcess" @([int]) @(process_id_here)
Run Code Online (Sandbox Code Playgroud)

当然,如果你经常需要它,你可以做到这alias一点.

  • 需要明确的是:如果程序死锁,那就是该程序中的错误。任何代码都不应该因为意外的时间而死锁。通用操作系统(不是 RTOS)有权以任何可以想象的顺序无限期地搁置任何和所有线程,即使事情按预期运行也是如此。我知道现实生活中的程序总是有错误,但我讨厌人们将其标准化为:“这不是正常行为,你暂停了一个我没想到的线程,所以任何事情都可能发生”。 (4认同)
  • 您的很好答案的第一句话是错误的。是的,您可以从命令行进行操作!从www.sysinternals.com下载PsSuspend。这个小工具甚至可以挂起在另一台计算机上运行的进程。https://technet.microsoft.com/zh-cn/sysinternals/bb897540.aspx (2认同)
  • 这些进程会在任务管理器的“状态”列中显示为“已暂停”吗? (2认同)
  • @Pacerier - 程序员有时会无意中在具有多个线程的程序中创建"竞争条件".竞争条件意味着程序以某种方式依赖于程序的两个独立执行部分完成事情的顺序.就像你知道你的朋友总是比你完成某项任务更快,所以你依赖于此.但如果你的朋友以某种方式被阻止,那么突然之间就不再是这样了.节目很精致.你可以调整一下.一个程序不能. (2认同)

Sig*_*oad 79

如果没有任何外部工具,您只需在Windows 7或8上完成此操作,方法是打开资源监视器,在CPU或Overview选项卡上右键单击该过程并选择Suspend Process.可以从任务管理器的"性能"选项卡启动"资源"监视器.

  • 不知何故,我第一次错过了它,但现在我在 Sysinternals 的进程资源管理器“procexp.exe”中右键单击进程时也看到了这个选项! (2认同)

Zor*_*dey 40

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

编辑:微软收购了SysInternals,url:procExp.exe

除此之外,您可以将进程优先级设置为低,以免它妨碍其他进程,但这不会暂停进程.


Ale*_*yin 19

来自SysInternals套件的PsSuspend命令行实用程序.它通过其id暂停/恢复进程.


shi*_*man 14

好吧,Process Explorer有一个暂停选项.您可以右键单击流程列中的流程,然后选择挂起.一旦你准备好再次恢复它,右键单击,这次选择简历.Process Explorer可以从这里获得:

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


Sti*_*ard 6

PsSuspend,如提及Vadzim,甚至,挂起/它的名字恢复的过程,不仅PID。

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

PsList -d onedrive|find/i "suspend" && PsSuspend -r onedrive || PsSuspend onedrive
Run Code Online (Sandbox Code Playgroud)

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