Unixでは、プロセスの実行を一時的に中断し、シグナルSIGSTOP
とで再開できSIGCONT
ます。プログラミングせずにWindowsでシングルスレッドプロセスを一時停止するにはどうすればよいですか?
7 に答える
コマンドラインからそれを行うことはできません。コードを作成する必要があります(ユーティリティを探しているだけではないと思います。そうでない場合は、スーパーユーザーの方が適している可能性があります)。また、アプリケーションにはそれを実行するために必要なすべての権限があると想定しています(例にはエラーチェックがありません)。
ハードウェイ
最初に特定のプロセスのすべてのスレッドを取得してから、関数を呼び出して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が指定されている場合)。構文は非常に単純です。停止するプロセスのIDを渡すだけです。コマンドラインアプリケーションを作成する場合は、プロセスを一時停止したままにする(または終了する)ために、インスタンスを実行し続ける必要があります。詳細については、MSDNの「備考」セクションを参照してください。
void suspend(DWORD processId)
{
DebugActiveProcess(processId);
}
コマンドラインから
私が言ったように、Windowsコマンドラインにはそれを行うためのユーティリティはありませんが、PowerShellからWindowsAPI関数を呼び出すことができます。最初にInvoke-WindowsApiスクリプトをインストールしてから、次のように記述できます。
Invoke-WindowsApi "kernel32" ([bool]) "DebugActiveProcess" @([int]) @(process_id_here)
もちろん、あなたがそれを頻繁に必要とするならば、あなたはそれのalias
ために作ることができます。
外部ツールがなくても、Windows 7、8、または10でこれを実行するには、リソースモニターを開き、[CPU]または[概要]タブでプロセスを右クリックし、[プロセスの一時停止]を選択します。リソースモニターは、タスクマネージャーの[パフォーマンス]タブから開始できます。
私はSysInternals(procexp.exe)の(非常に古い)ProcessExplorerを使用しています。これは、標準のタスクマネージャーの置き換え/追加であり、そこからプロセスを一時停止できます。
編集:MicrosoftはSysInternalsを買収しました。URL:procExp.exe
それ以外の場合は、プロセスの優先度を低く設定して、他のプロセスの邪魔にならないようにすることができますが、これによってプロセスが中断されることはありません。
スイートのPsSuspendコマンドラインユーティリティSysInternals
。IDによってプロセスを一時停止/再開します。
そうですね、ProcessExplorerには一時停止オプションがあります。プロセス列でプロセスを右クリックし、[一時停止]を選択できます。再開する準備ができたら、右クリックして、今度は再開を選択します。Process Explorerは、次の場所から入手できます。
http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx
Vadzimが述べているように、PsSuspendは、pidだけでなく、その名前でプロセスを一時停止/再開します。
OneDriveプロセスの単純なトグルスクリプトでPsSuspendとPsList(PsToolsスイートの別のツール)の両方を使用します。より多くの帯域幅が必要な場合は、OneDrive同期を一時停止し、その後、同じミニスクリプトを発行してプロセスを再開します。
PsList -d onedrive|find/i "suspend" && PsSuspend -r onedrive || PsSuspend onedrive
スイートのPsSuspendコマンドラインユーティリティSysInternals
。IDによってプロセスを一時停止/再開します。
#pragma comment(lib,"ntdll.lib")
EXTERN_C NTSTATUS NTAPI NtSuspendProcess(IN HANDLE ProcessHandle);
void SuspendSelf(){
NtSuspendProcess(GetCurrentProcess());
}
ntdllには、エクスポートされた関数NtSuspendProcessが含まれており、トリックを実行するためにハンドルをプロセスに渡します。