86

在 Unix 中,我们可以暂时暂停进程执行并使用信号SIGSTOPSIGCONT. 如何在不编程的情况下挂起 Windows 中的单线程进程?

4

7 回答 7

107

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

艰辛的道路

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

请注意,这个功能过于幼稚,要恢复线程,您应该跳过暂停的线程,并且由于暂停/恢复顺序很容易导致死锁。对于单线程应用程序,它很冗长,但它可以工作。

无证方式

从 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),语法非常简单:只需传递你想要停止的进程的 ID et-voila。如果您要创建一个命令行应用程序,您需要保持其实例运行以保持进程暂停(或者它将被终止)。有关详细信息,请参阅 MSDN 上的备注部分。

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

从命令行

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

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

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

于 2012-06-13T07:59:04.200 回答
90

无需任何外部工具,您可以在 Windows 7、8 或 10 上简单地完成此操作,方法是打开资源监视器并在 CPU 或概览选项卡上右键单击进程并选择暂停进程。资源监视器可以从任务管理器的性能选项卡中启动。

于 2014-02-08T17:46:46.697 回答
41

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

编辑:微软已经收购了 SysInternals,网址:procExp.exe

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

于 2012-06-13T07:59:43.270 回答
23

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

于 2013-11-21T06:20:00.673 回答
14

好吧,Process Explorer 有一个挂起选项。您可以在进程列中右键单击一个进程,然后选择挂起。一旦您准备好再次恢复它,请右键单击,这次选择恢复。Process Explorer 可以从这里获得:

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

于 2013-04-12T11:11:17.713 回答
6

正如 Vadzim所提到的,PsSuspend甚至可以通过名称暂停/恢复进程,而不仅仅是通过 pid。

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

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

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

于 2019-06-21T13:56:28.797 回答
0
#pragma comment(lib,"ntdll.lib")
EXTERN_C NTSTATUS NTAPI NtSuspendProcess(IN HANDLE ProcessHandle);

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

ntdll 包含导出的函数 NtSuspendProcess,将句柄传递给进程以完成此操作。

于 2019-02-11T03:41:58.870 回答