Як призупинити / відновити процес у Windows?


77

У Unix ми можемо тимчасово призупинити виконання процесу та відновити його за допомогою сигналів SIGSTOPі SIGCONT. Як я можу призупинити однопотоковий процес у Windows без програмування?



Просто для того, щоб додати дрібку педантизму, процес Unix також може бути призупинений за допомогою SIGTSTPвідображення карт Ctrl-Zв оболонці.
bfx

Відповіді:


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.

Ця функція дозволяє зупинити процес (з урахуванням його ідентифікатора процесу), синтаксис дуже простий: просто передайте ідентифікатор процесу, який ви хочете зупинити et-voila. Якщо ви створюєте програму командного рядка, вам потрібно буде постійно запускати її екземпляр, щоб тримати процес призупиненим (або він буде припинений). Див розділі " Зауваження " про MSDN.

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

З командного рядка

Як я вже казав, у командному рядку Windows немає жодної утиліти для цього, але ви можете викликати функцію Windows API із PowerShell. Спочатку встановіть скрипт Invoke-WindowsApi, тоді ви можете написати це:

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

Звичайно, якщо вам це потрібно часто, ви можете зробити aliasдля цього.


Що ви маєте на увазі, коли говорите "встановити Invoke-WindowsApi"?
MemphiZ

@MemphiZ це невеликий Командлети ( Invoke-WindowsApi) , що дозволить вам Invoke в Windows API , (PASCAL угода про виклики, звичайно WINAPI) функцію C. Він не є частиною PowerShell, тоді його потрібно завантажити та встановити окремо .
Адріано Репетті

2
Перше речення вашої дуже доброї відповіді є неправильним. Так, ви МОЖЕТЕ це зробити з командного рядка! Завантажте PsSuspend з www.sysinternals.com. Цей маленький інструмент може навіть призупинити процеси, які працюють на іншому комп'ютері. technet.microsoft.com/en-us/sysinternals/bb897540.aspx
Elmue

1
Чи відображатимуться ці процеси як "Призупинено" у стовпці Статус диспетчера завдань?
CMCDragonkai

2
@Pacerier - Програмісти іноді ненавмисно створюють "умови перегонів" у програмах з декількома потоками. Умови перегонів означають, що програма якимось чином залежить від порядку, в якому речі виконуються двома незалежно виконуючими частинами програми. Це наче ви знаєте, що ваш друг завжди виконує певне завдання швидше, ніж ви, і тому ви залежате від цього. Але якщо вашого друга якось затримали, то раптом це вже не так. Програми делікатні. Ви можете налаштувати, можливо. Програма не може.
Всезначний

84

Без будь-якого зовнішнього інструменту ви можете просто досягти цього в Windows 7 або 8, відкривши монітор ресурсів і на вкладці ЦП або Огляд правою кнопкою миші на процесі та вибравши Призупинити процес . Монітор ресурсів можна запустити з вкладки "Ефективність" диспетчера завдань.


@Sigroad, чи робить resmon.exe те саме, що і відповідь Адріано?
Пейс'єр

@Pacerier На жаль, я не знаю, як resmon.exe працює внутрішньо.
Sigroad

2
Якось я пропустив це вперше, але тепер я бачу варіант для цього, коли також клацніть правою кнопкою миші на процесі в Провіднику процесів Sysinternals procexp.exe!
Pysis

41

Я використовую (дуже старий) провідник процесів від SysInternals (procexp.exe). Це заміна / доповнення до стандартного диспетчера завдань, звідти ви можете призупинити процес.

Редагувати: Microsoft придбала SysInternals, url: procExp.exe

Крім цього, ви можете встановити пріоритет процесу на низький, щоб він не заважав іншим процесам, але це не призупинить процес.


1
це майже ідеально відповідає на питання, не знаю, чому воно не отримало більше голосів.
Лауер

Чи можете ви призупинити процес, перевести комп'ютер у режим сну, а потім перезапустити процес знову, коли він прокинеться? У мене є утиліта, яка повинна працювати кілька днів (загалом), але я не хочу залишати комп’ютер цілодобово.
posfan12

@ posfan12 Чому б просто не перевести комп'ютер у режим сну? Як не пов’язаний приклад, коли одне з моїх вікон було зведено до мінімуму, воно вже мало низький пріоритет у фоновому режимі 4 з приблизно 24 на 4. Відповідь shivesh suman, схоже, охоплює кращий варіант у тому ж програмному забезпеченні.
Pysis

"Чому б просто не перевести комп'ютер у режим сну?" Тому що я не хочу, щоб процес повністю переривався.
posfan12


14

Ну, у Process Explorer є опція призупинення. Ви можете клацнути правою кнопкою миші процес у стовпці процесу та вибрати призупинити. Як тільки ви будете готові відновити його знову, клацніть правою кнопкою миші, і цього разу виберіть відновити. Провідник процесів можна отримати тут:

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


5

PsSuspend , як згадував Вадзім , навіть призупиняє / відновлює процес за назвою, а не лише за допомогою pid.

Я використовую і PsSuspend, і PsList (інший інструмент із набору PsTools) у простому сценарії перемикання для процесу OneDrive: якщо мені потрібна більша пропускна здатність, я призупиняю синхронізацію OneDrive, після чого відновлюю процес, видаючи той самий міні-сценарій:

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

Утиліта командного рядка PsSuspend із SysInternalsнабору. Він призупиняє / відновлює процес за своїм ідентифікатором.


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

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

ntdll містить експортовану функцію NtSuspendProcess, передайте дескриптор процесу, щоб виконати фокус.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.