web-dev-qa-db-ja.com

Windowsでプロセスを中断/再開する方法は?

Unixでは、プロセスの実行を一時的に中断し、SIGSTOPおよびSIGCONTのシグナルで再開できます。プログラミングせずにWindowsでシングルスレッドプロセスを一時停止するにはどうすればよいですか?

66
Michael

あなたはコマンドラインからそれを行うことができません、あなたはいくつかのコードを書かなければなりません(私はあなたがユーティリティを探しているだけではないと思います、さもなければスーパーユーザーは尋ねるより良い場所かもしれません)。また、あなたのアプリケーションはそれを行うために必要なすべての許可を持っていると仮定します(例はエラーチェックなしです)。

ハードウェイ

最初に特定のプロセスのすべてのスレッドを取得してから、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がありますが、それはundocumentedです。コード例については この投稿 をお読みください(文書化されていない関数のリファレンス: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を作成できます。

90
Adriano Repetti

外部ツールがなくても、リソースモニターを開き、CPUまたは[概要]タブでプロセスを右クリックしてプロセスの一時停止を選択することで、Windows 7または8でこれを簡単に実行できます。リソースモニターは、タスクマネージャーの[パフォーマンス]タブから起動できます。

79
Sigroad

SysInternals(procexp.exe)の(非常に古い)プロセスエクスプローラーを使用します。これは、標準のタスクマネージャーの代替/追加であり、そこからプロセスを一時停止できます。

編集:MicrosoftはSysInternalsを購入しました、URL: procExp.exe

それ以外は、プロセスの優先度を低く設定して、他のプロセスの邪魔にならないようにすることができますが、これはプロセスを中断しません。

40
Zordey

PsSuspendSysInternalsスイートのコマンドラインユーティリティ。 IDによってプロセスを一時停止/再開します。

19
AlexeyDaryin

さて、Process Explorerには中断オプションがあります。プロセス列でプロセスを右クリックして、中断を選択できます。再開する準備ができたら、右クリックして、再開を選択します。 Process Explorerはここから入手できます。

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

14
shivesh suman

PsSuspendVadzim で述べたように、pidだけでなく、名前でプロセスを一時停止/再開します。

OneDriveプロセスの単純なトグルスクリプトでPsSuspendと PsList (PsToolsスイートの別のツール)の両方を使用します。より多くの帯域幅が必要な場合は、OneDrive同期を一時停止し、その後、発行してプロセスを再開します同じミニスクリプト:

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

PsSuspendSysInternalsスイートのコマンドラインユーティリティ。 IDによってプロセスを一時停止/再開します。

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

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

ntdllにはエクスポートされた関数NtSuspendProcessが含まれており、プロセスにハンドルを渡してトリックを実行します。

0
coltonon