Wie kann ich einen Prozess in Windows anhalten / fortsetzen?

77

Unter Unix können wir eine Prozessausführung vorübergehend unterbrechen und mit Signalen SIGSTOPund fortsetzen SIGCONT. Wie kann ich einen Single-Thread-Prozess in Windows ohne Programmierung anhalten?

Michael
quelle
2
mögliches Duplikat von Wie kann ich die Ausführung eines Programms einfrieren?
Hans Passant
Nur um eine Prise Pedanterie hinzuzufügen, kann auch ein Unix-Prozess angehalten werden, durch SIGTSTPden Zuordnungen Ctrl-Zin der Shell vorgenommen werden.
bfx

Antworten:

102

Sie können es nicht über die Befehlszeile tun, Sie müssen Code schreiben (ich nehme an, Sie suchen nicht nur nach einem Dienstprogramm, sonst ist Super User möglicherweise ein besserer Ort, um zu fragen). Ich gehe auch davon aus, dass Ihre Anwendung über alle erforderlichen Berechtigungen verfügt (Beispiele sind ohne Fehlerprüfung).

Harter Weg

Holen Sie sich zuerst alle Threads eines bestimmten Prozesses und rufen Sie dann die SuspendThreadFunktion auf, um jeden einzelnen zu stoppen (und ResumeThreadfortzusetzen). Es funktioniert, aber einige Anwendungen können abstürzen oder hängen bleiben, weil ein Thread an einem beliebigen Punkt gestoppt werden kann und die Reihenfolge des Anhaltens / Fortsetzens nicht vorhersehbar ist (dies kann beispielsweise zu einer Deadlock führen). Für eine Single-Threaded-Anwendung ist dies möglicherweise kein Problem.

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);
}

Bitte beachten Sie, dass diese Funktion sogar zu naiv ist. Um Threads fortzusetzen, sollten Sie gesperrte Threads überspringen. Aufgrund der Reihenfolge des Suspendierens / Fortsetzens kann es leicht zu einem Deadlock kommen. Für Single-Threaded-Anwendungen ist es Prolix, aber es funktioniert.

Undokumentierter Weg

Ab Windows XP gibt es das, NtSuspendProcessaber es ist nicht dokumentiert . In diesem Beitrag finden Sie ein Codebeispiel (Referenz für undokumentierte Funktionen: 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);
}

"Debugger" Weg

Ein Programm anzuhalten ist das, was normalerweise ein Debugger tut. Dazu können Sie die DebugActiveProcessFunktion verwenden. Die Prozessausführung wird angehalten (mit allen Threads zusammen). Zum Fortsetzen können Sie verwenden DebugActiveProcessStop.

Mit dieser Funktion können Sie einen Prozess stoppen (anhand seiner Prozess-ID). Die Syntax ist sehr einfach: Übergeben Sie einfach die ID des Prozesses, den Sie et-voila stoppen möchten. Wenn Sie eine Befehlszeilenanwendung erstellen, müssen Sie deren Instanz weiter ausführen, damit der Prozess angehalten bleibt (oder er wird beendet). Weitere Informationen finden Sie im Abschnitt " Anmerkungen " zu MSDN.

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

Über die Befehlszeile

Wie gesagt, die Windows-Befehlszeile verfügt über kein Dienstprogramm, aber Sie können eine Windows-API-Funktion über PowerShell aufrufen. Installieren Sie zuerst das Invoke-WindowsApi- Skript, dann können Sie Folgendes schreiben:

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

Natürlich, wenn Sie es oft brauchen, können Sie eine aliasdafür machen .

Adriano Repetti
quelle
Was meinst du mit "install Invoke-WindowsApi"?
MemphiZ
@MemphiZ es ein kleines Cmdlets (ist Invoke-WindowsApi) , die Sie lassen invoke eine Windows - API ( PASCALAufrufkonvention, allgemein WINAPI) C - Funktion. Es ist nicht Teil von PowerShell, dann muss es separat heruntergeladen und installiert werden .
Adriano Repetti
2
Der erste Satz Ihrer sehr guten Antwort ist falsch. Ja, Sie können es von der Kommandozeile aus tun! Laden Sie PsSuspend von www.sysinternals.com herunter. Dieses kleine Tool kann sogar Prozesse anhalten, die auf einem anderen Computer ausgeführt werden. technet.microsoft.com/en-us/sysinternals/bb897540.aspx
Elmue
1
Werden diese Prozesse in der Spalte Status des Task-Managers als "Angehalten" angezeigt?
CMCDragonkai
2
@Pacerier - Programmierer erstellen manchmal unbeabsichtigt "Rennbedingungen" in Programmen mit mehreren Threads. Die Rennbedingungen bedeuten, dass das Programm irgendwie von der Reihenfolge abhängt, in der die Dinge von zwei unabhängig ausgeführten Teilen des Programms ausgeführt werden. Es ist, als ob Sie wissen, dass Ihr Freund eine bestimmte Aufgabe immer schneller erledigt als Sie, und deshalb sind Sie darauf angewiesen. Aber wenn dein Freund irgendwie aufgehalten wird, ist das plötzlich nicht mehr der Fall. Programme sind heikel. Sie können sich vielleicht anpassen. Ein Programm kann nicht.
Omnifarious
83

Ohne ein externes Tool können Sie dies einfach unter Windows 7 oder 8 erreichen, indem Sie den Ressourcenmonitor und auf der Registerkarte CPU oder Übersicht mit der rechten Maustaste auf den Prozess klicken und Prozess anhalten auswählen . Der Ressourcenmonitor kann auf der Registerkarte Leistung des Task-Managers gestartet werden.

Sigroad
quelle
@Sigroad, macht resmon.exe dasselbe wie Adrianos Antwort?
Pacerier
@ Pacerier Leider ist mir nicht bekannt, wie resmon.exe intern funktioniert.
Sigroad
1
Irgendwie habe ich es das erste Mal verpasst, aber jetzt sehe ich die Option dafür, wenn ich auch im Prozess-Explorer von Sysinternals mit der rechten Maustaste auf den Prozess klicke procexp.exe!
Pysis
41

Ich verwende (einen sehr alten) Prozess-Explorer von SysInternals (procexp.exe). Es ist ein Ersatz / eine Ergänzung zum Standard-Task-Manager. Von dort aus können Sie einen Prozess anhalten.

Bearbeiten: Microsoft hat über SysInternals gekauft, URL: procExp.exe

Ansonsten können Sie die Prozesspriorität auf niedrig setzen, damit sie anderen Prozessen nicht im Wege steht. Dadurch wird der Prozess jedoch nicht angehalten.

Zordey
quelle
1
Dies beantwortet die Frage fast perfekt, weiß nicht, warum es nicht mehr positive Stimmen bekommen hat.
Lauer
Können Sie einen Prozess anhalten, Ihren Computer in den Energiesparmodus versetzen und den Prozess nach dem Aufwachen erneut starten? Ich habe ein Dienstprogramm, das mehrere Tage (insgesamt) ausgeführt werden muss, aber ich möchte meinen Computer nicht rund um die Uhr laufen lassen.
Posfan12
@ posfan12 Warum nicht einfach den Computer in den Ruhezustand versetzen? Als ein nicht verwandtes Beispiel, als eines meiner Fenster minimiert wurde, hatte es bereits eine niedrige Hintergrundpriorität von 4 von etwa 24 bis 4. Die Antwort von shivesh suman scheint eine bessere Option in derselben Software abzudecken.
Pysis
"Warum nicht einfach den Computer in den Ruhezustand versetzen?" Weil ich nicht möchte, dass der Prozess vollständig unterbrochen wird.
Posfan12
22

PsSuspend- Befehlszeilenprogramm aus der SysInternalsSuite. Es unterbricht / setzt einen Prozess anhand seiner ID fort.

AlexeyDaryin
quelle
14

Nun, Process Explorer hat eine Suspend-Option. Sie können mit der rechten Maustaste auf einen Prozess in der Prozessspalte klicken und Suspend auswählen. Sobald Sie bereit sind, es wieder aufzunehmen, klicken Sie mit der rechten Maustaste und wählen Sie dieses Mal Fortsetzen. Der Prozess-Explorer ist hier erhältlich:

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

Shivesh Suman
quelle
5

PsSuspend unterbricht , wie von Vadzim erwähnt , sogar einen Prozess mit seinem Namen, nicht nur mit pid.

Ich verwende sowohl PsSuspend als auch PsList (ein weiteres Tool aus der PsTools-Suite) in einem einfachen Umschaltskript für den OneDrive-Prozess: Wenn ich mehr Bandbreite benötige, unterbreche ich die OneDrive-Synchronisierung und setze den Prozess anschließend fort, indem ich dasselbe Miniskript ausstelle:

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

PsSuspend- Befehlszeilenprogramm aus der SysInternalsSuite. Es unterbricht / setzt einen Prozess anhand seiner ID fort.

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

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

ntdll enthält die exportierte Funktion NtSuspendProcess. Übergeben Sie das Handle an einen Prozess, um den Trick auszuführen.

Coltonon
quelle