Seite 1 von 1

win32 Prozesse anhalten

Verfasst: Donnerstag 14. Februar 2008, 10:43
von droptix
Suche sowas hier für Python: http://aspn.activestate.com/ASPN/CodeDo ... ocess.html

Das ist ein Perl-Paket, mit dem man Prozesse manipulieren kann, also z.B. anhalten und wieder laufen lassen. Genau dieses Feature suche ich zurzeit, habe aber bei Tim Golden's WMI Stuff oder in den win32 Extensions nichts Vergleichbares gefunden.

[Edit:] Im Modul win32process gibt's die Funktionen SuspendThread und ResumeThread, aber das geht eben nicht für Prozesse. Außerdem möchte ich den Prozess nicht selbst via CreateProcess erstellen, sondern einen vorhandenen aus der Prozessliste auslesen und dann anhalten können.

Tags: win32 process suspend resume Prozess anhalten

Verfasst: Freitag 15. Februar 2008, 14:03
von droptix
Also ich bin einen kleinen Schritt weiter: Ich brauche zuerst einen ProcessHandler. Den bekomme ich entweder, wenn ich einen neuen Prozess erstelle oder einen laufenden Prozess über seine ProcessId "öffne":

Code: Alles auswählen

processHandle = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, False, processId)
Dann bin ich an der Stelle, dass ich zwar einen ProcessHandler habe, aber Python mir keine Methode wie suspend oder so zur Verfügung stellt. Perl hat es irgendwie geschafft, mit Win32::Process eine solche Methode zu integrieren.

Code: Alles auswählen

$ProcessObj->Suspend()
    Suspend the process associated with the $ProcessObj. 
$ProcessObj->Resume()
    Resume a suspended process.
Mit Python habe ich suspend und resume aber für Threads. Und da ein Prozess aus mindestens einem Thread besteht, müsste ich nun nur noch alle Threads des Prozesses auslesen können, um sie zu beenden. Aber auch da scheitert's. Was ich derzeit an Wissen habe ist folgendes:

Code: Alles auswählen

threadHandle = win32api.GetCurrentThread()
# suspending the *current* handle will freeze the Python program itself  :)  no good idea!
win32process.SuspendThread(threadHandle)
Ich brauch also sowas wie GetAllThreads(processHandle), aber das kann ich nicht finden.

Verfasst: Freitag 15. Februar 2008, 15:24
von Mad-Marty
Empfohlene Lektüre:
http://www.codeproject.com/KB/threads/pausep.aspx

Lösungsansatz:
Enumerate über die Threads deines Zielprocesses, und benutze win32process.SuspendThread() auf alle Threads des Prozesses.

Wofür braucht man sowas überhaupt?
Was ist das für eine völlig vermurkste Software die du versuchst damit zu Steuern?

Verfasst: Freitag 15. Februar 2008, 15:38
von gerold
Das wird ein Python-Virus, der den Virenscanner aufhalten soll. :lol:

Verfasst: Freitag 15. Februar 2008, 16:19
von droptix
Oh mann, das wird ja härter als ich gedacht habe… Also das bestätigt meine Befürchtungen, dass ich erst alle Threads eines Prozesses auslesen muss, um ein SuspendThread() über jeden einzelnen Thread laufen zu lassen.

Wofür man sowas braucht steht ja im Link ganz gut beschrieben. Wenn der Rechner durch einen dummen Prozess voll ausgelastet ist und man schnell mal eben was anderes machen muss, sind einem oft die Hände gebunden.

Ich hatte aber nicht gedacht, dass diese Methode so unsicher und fehleranfällig ist. Daher werde ich wohl weiter nach etwas anderem suchen. Da Perl eine Suspend-Methode für ein Prozess-Objekt anbietet und sich auch nur auf die Win32 API beruft, gehe ich davon aus dass Windows grundsätzlich zu sowas in der Lage ist. Nur eben wird das in den Python Win32 Extensions noch nicht aufgenommen sein…

Also ich bin über weitere Tipps sehr dankbar!

Verfasst: Freitag 15. Februar 2008, 16:31
von Leonidas
droptix hat geschrieben:Da Perl eine Suspend-Methode für ein Prozess-Objekt anbietet und sich auch nur auf die Win32 API beruft, gehe ich davon aus dass Windows grundsätzlich zu sowas in der Lage ist. Nur eben wird das in den Python Win32 Extensions noch nicht aufgenommen sein…
Naja, das heißt ja nicht das Perl die API 1:1 abbilden muss. Pygame ist auch ein Wrapper um die SDL, kann aber mehr als die SDL auf C-Ebene, weil es eben einige Convenience-Funktionen hat.

Verfasst: Freitag 15. Februar 2008, 17:39
von droptix
Mir schoss grad noch ein ganz anderer Ansatz in den Kopf: Wie macht das denn ein Virenscanner? Nehmen wir an ich starte eine ausführbare Datei. Nun steigt der Virenscanner für gewöhnlich erstmal ein, prüft die Datei und entscheidet dann weiter… während der Prüfphase wird doch alles geblockt. Ich stelle mir das als Prozess-Pause vor. Erst wenn die Datei in Ordnung ist, lässt der Virenscanner den Prozess weiter laufen.

Läuft das so oder völlig anders?

[Edit 1:] Wie ich soeben gefunden habe:
Windows Server Cookbook 2005 hat geschrieben:Suspending a Process
Problem
You want to suspend a process from running. This is helpful if you want to temporarily stop an application from running, perhaps due to high CPU consumption, but you don't want to kill it. This can give you an opportunity to launch further diagnostic utilities to troubleshoot the process.

Solution
Using a graphical user interface
Open the Sysinternals Process Explorer tool (procexp.exe). To suspend a process, right-click on the target process and select Suspend. To resume a process, right-click on the target process and select Resume.

Using a command-line interface
The following command suspends a process:

> pssuspend <PID>


Replace <PID> with the process ID of the target process.

The following command resumes a suspended process:

> pssuspend -r <PID>


Using VBScript
Currently, no scripting API supports suspending processes. However, you can use the SuspendThread and ResumeThread functions that are defined in kernel.lib if you are using a high-level language such as Visual Basic or C++.
[Edit 2:] pssuspend kann man sich bei MS runterladen.

ntdll NtSuspendProcess NtResumeProcess

Verfasst: Montag 25. Februar 2008, 08:40
von droptix
Hab herausgefunden, dass in der NT API Funktionen zum Anhalten und Fortfahren von Prozessen gibt. In einem C++ Forum wurde mir dieser Code gegeben.

Ich habe nun versucht das mittels ctypes in mein Python-Programm zu übernehmen. Ich kann die entsprechenden Funktionen auch ansprechen und die korrekten Argumente übergeben, allerdings passiert nichts:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-

import wmi
import ctypes
import time

TIMEOUT = 15

def main():
    c = wmi.WMI()
    watcher = c.Win32_Process.watch_for("creation")
    processHandle = watcher()
    print "Suspend", processHandle.Caption
    ctypes.windll.ntdll.NtSuspendProcess(processHandle.Handle)
    print "Wait %d seconds..." % TIMEOUT
    time.sleep(TIMEOUT)
    print "Resume", processHandle.Caption
    ctypes.windll.ntdll.NtResumeProcess(processHandle.Handle)

if __name__ == "__main__":
    main()
Startet einfach mal nach dem Programmstart innerhalb von 15 Sekunden (s. TIMEOUT) ein beliebiges Programm, z.B. calc.exe. Der Prozess wird erkannt, kann aber nicht angehalten werden. Irgendwie landet die Wirkung von NtSuspendProcess im Nirvana...

Hat vielleicht noch jemand eine clevere Idee dazu?