Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Fremdes Programm/Anwendung pausieren? (https://www.delphipraxis.net/134711-fremdes-programm-anwendung-pausieren.html)

Yakumo500 27. Mai 2009 14:06


Fremdes Programm/Anwendung pausieren?
 
Hiho,

Ist es möglich irgendwie eine fremde Anwendung zu pausieren?

brechi 27. Mai 2009 14:17

Re: Fremdes Programm/Anwendung pausieren?
 
SuspendThread
ResumeThread

könnte helfen, dann ist das Programm aber blockiert (reagiert auf keine Eingaben mehr)

Yakumo500 27. Mai 2009 17:57

Re: Fremdes Programm/Anwendung pausieren?
 
Danke kannst du mir auch sagen wie ich den Main Thread eines Prozesses bekomme?

quendolineDD 27. Mai 2009 18:01

Re: Fremdes Programm/Anwendung pausieren?
 
Mit MSDN-Library durchsuchenOpenThread bekommst du das Handle zu dem Thread zurück, was du für MSDN-Library durchsuchenSuspendThread und MSDN-Library durchsuchenResumeThread benötigst.

brechi 27. Mai 2009 18:58

Re: Fremdes Programm/Anwendung pausieren?
 
An den Mainthread komsmt du z.B. mittels

http://msdn.microsoft.com/en-us/library/ms682489(VS.85).aspx (tlhelp32)

Fridolin Walther 27. Mai 2009 19:26

Re: Fremdes Programm/Anwendung pausieren?
 
Nur damit das klar ist: So etwas wie einen "Main Thread" gibt es nicht. Du musst um einen Prozess zu pausieren alle in ihm befindlichen Threads pausieren (suspenden).

Luckie 27. Mai 2009 20:39

Re: Fremdes Programm/Anwendung pausieren?
 
Zitat:

Zitat von 0xF30FC7
Nur damit das klar ist: So etwas wie einen "Main Thread" gibt es nicht. Du musst um einen Prozess zu pausieren alle in ihm befindlichen Threads pausieren (suspenden).

... und dann beten, dass der Prozess keine Ressourcen gesperrt hat, auf die ein anderer Prozess wartet. ;)

Fridolin Walther 27. Mai 2009 22:27

Re: Fremdes Programm/Anwendung pausieren?
 
Das muss nicht mal ein anderer Prozess sein. Du glaubst gar nicht wieviele Prozesse das Resume von sich aus schon nicht überleben. Insbesondere dann wenn die Anwendungen Multi Threading verwenden. Dadurch das Du die Thread Reihenfolge beim Suspenden und Resumen nicht so wirklich festlegen kannst, kommts da durchaus häufiger mal zu Crashes.

brechi 28. Mai 2009 12:04

Re: Fremdes Programm/Anwendung pausieren?
 
Also das Suspenden/Resumen sollte eigentlich im theoretischem kein Problem darstellen. Man darf halt auch nru die Threads Resumen die wirklich suspended waren (siehe Counter). Ansonsten sollte das Programm keinen Unterschied merken ob es im Usermode (druch Suspend) bzw. vom Scheduler suspended/resumed wurde. Wenn die Reihenfolge vom Resume wirklich Auswirkungen haben sollte, dann ist das Programm ebene nicht Threadsafe programmiert.

Und meiner Meinung nach sollte auch ein Hauptthread existieren, ohne den kein anderer Thread laufen würde. Wenn der Abschossen wird, dann beendet sich das komplette Programm. Von daher sollte dieser zu letzt Suspended und zuerst Resumed werden.

Luckie 28. Mai 2009 12:11

Re: Fremdes Programm/Anwendung pausieren?
 
Und wie findet man den Hauptthread?

Also bei einer GUI-Anwendung ist der Hauptthread, der Thread der zum Hauptfenster gehört.

Fridolin Walther 28. Mai 2009 12:33

Re: Fremdes Programm/Anwendung pausieren?
 
Zitat:

Zitat von brechi
Also das Suspenden/Resumen sollte eigentlich im theoretischem kein Problem darstellen.

In der Theorie gibts da sogar noch mehr Probleme. Timeouts laufen auch weiter während der Prozess suspended ist. Je nach Timeout der getriggert wird, gibts da durchaus lustige Effekte.

Zitat:

Zitat von brechi
Man darf halt auch nru die Threads Resumen die wirklich suspended waren (siehe Counter).

Wieso? Wenn ich alle Thread suspende (-> alle Suspend Counter incrementiere), darf ich danach ja auch wieder alle resumen (-> alle Suspend Counter decrementieren).

Zitat:

Zitat von brechi
Wenn die Reihenfolge vom Resume wirklich Auswirkungen haben sollte, dann ist das Programm ebene nicht Threadsafe programmiert.

Oder aber man triggert irgendwelche Timeouts, die bei Multithreaded Applications ja durchaus häufiger mal zu finden sind.

Zitat:

Zitat von brechi
Und meiner Meinung nach sollte auch ein Hauptthread existieren, ohne den kein anderer Thread laufen würde. Wenn der Abschossen wird, dann beendet sich das komplette Programm. Von daher sollte dieser zu letzt Suspended und zuerst Resumed werden.

Es ist zwar so, daß ohne den ersten Thread alle anderen Threads nicht laufen würden, allerdings wird ein Prozess von Windows erst dann beendet, wenn alle Threads beendet wurden. Für Windows gibts zw. den Threads letztlich keinen Unterschied. Von einem Main Thread zu sprechen ist daher höchst irreführend.

Als kleine Demonstration:
Delphi-Quellcode:
program ThreadDemonstration;

{$APPTYPE CONSOLE}

uses
  windows, sysutils;

function ThreadProcedure(NotUsed : pointer) : Integer; stdcall;
begin
  writeln('Thread aktiv - ID: ', GetCurrentThreadID, ' - Handle: ', GetCurrentThread);
  Sleep(INFINITE);
  Result := 0;
end;

var
  ThreadID : dword;
begin
  CloseHandle(CreateThread(nil, 0, @ThreadProcedure, nil, 0, ThreadID));
  TerminateThread(GetCurrentThread, 0); // Unschön, muss aber leider sein, weil beim Verlassen des Code Blocks ansonsten ein explizites ExitProcess aufgerufen wird
end.

Yakumo500 28. Mai 2009 13:00

Re: Fremdes Programm/Anwendung pausieren?
 
Hier habe ich auch eine Exe gefunden allerdings in C++ geschrieben, die Prozesse per PID anhalten kann

HIER

Fridolin Walther 28. Mai 2009 13:03

Re: Fremdes Programm/Anwendung pausieren?
 
Ja, die macht auch nichts anderes als alle Threads eines Prozesses zu enumerieren und SuspendThread bzw. ResumeThread für jeden Thread aufzurufen.

Yakumo500 28. Mai 2009 13:05

Re: Fremdes Programm/Anwendung pausieren?
 
Muss ich eine Datei in uses hinzufügen um OpenThread nutzen zu können?

Fridolin Walther 28. Mai 2009 13:06

Re: Fremdes Programm/Anwendung pausieren?
 
Ja, windows :).

Yakumo500 28. Mai 2009 13:08

Re: Fremdes Programm/Anwendung pausieren?
 
Komisch ich habe Windows bei uses eingetragen aber er kennt die Funktion trotzdem nicht. (Ich habe Delphi 7)

Fridolin Walther 28. Mai 2009 13:12

Re: Fremdes Programm/Anwendung pausieren?
 
Benutz halt ansonsten folgende Definition:
Delphi-Quellcode:
function OpenThread(dwDesiredHandle : DWORD; bInheritHandle : LongBool; dwThreadID : DWORD) : DWORD; stdcall; external 'kernel32.dll';

Fridolin Walther 28. Mai 2009 13:49

Re: Fremdes Programm/Anwendung pausieren?
 
Falls es jemanden interessiert:
Delphi-Quellcode:
const
  THREAD_SUSPEND_RESUME = $0002;

function OpenThread(dwDesiredHandle : DWORD; bInheritHandle : LongBool; dwThreadID : DWORD) : DWORD; stdcall; external 'kernel32.dll';

function ResumeOrSuspendProcess(PID : DWORD; Suspend : Boolean) : Boolean;
var
  SnapshotHandle : THandle;
  ThreadEntry   : TThreadEntry32;
  ThreadHandle  : THandle;
begin
  Result := false;
  ThreadEntry.dwSize := SizeOf(ThreadEntry);
  SnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
  if SnapshotHandle <> INVALID_HANDLE_VALUE then
    begin
      Result := true;
      if Thread32First(SnapshotHandle, ThreadEntry) then
        repeat
          if ThreadEntry.th32OwnerProcessID = PID then
            begin
              ThreadHandle := OpenThread(THREAD_SUSPEND_RESUME, false, ThreadEntry.th32ThreadID);
              if ThreadHandle <> INVALID_HANDLE_VALUE then
                begin
                  if Suspend
                    then Result := (SuspendThread(ThreadHandle) <> DWORD(-1)) and Result
                    else Result := (ResumeThread(ThreadHandle) <> DWORD(-1)) and Result;
                  CloseHandle(ThreadHandle);
                end;
            end;
        until not Thread32Next(SnapshotHandle, ThreadEntry);
      CloseHandle(SnapshotHandle);
    end;
end;

function ResumeProcess(PID : DWORD) : Boolean;
begin
  Result := ResumeOrSuspendProcess(PID, false);
end;

function SuspendProcess(PID : DWORD) : Boolean;
begin
  Result := ResumeOrSuspendProcess(PID, true);
end;
Kann sein, daß das Fehlerhandling nicht 100% astrein ist. Hab die Funktionen auch nur eher notdürftig getestet.

Hinweis:
Die Funktion liefert true zurück, sobald eine Threadliste erstellt werden konnte. Falls also eine nicht existierende PID angegeben wurde, wird true zurück gegeben auch wenn keine Aktionen durchgeführt wurden. Der Suspend Counter der Threads werden nicht überprüft.

Yakumo500 28. Mai 2009 14:02

Re: Fremdes Programm/Anwendung pausieren?
 
Lol grad eben wollte ich auch meine jetzt funktionierende Version schreiben.
Ich machs einfach mal:

Benötigte Uses: Windows, Tlhelp32;

Delphi-Quellcode:
const
  THREAD_SUSPEND_RESUME = $0002;

function PauseProcess(PID: DWORD; F_Pause: boolean): boolean;
var NewThread: Cardinal;
    ThreadSnap: HWND;
    Te32: THREADENTRY32;
begin
  ThreadSnap := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);

  If ThreadSnap = INVALID_HANDLE_VALUE Then
  Begin
    Result := False;
    Exit;
  End;

  Te32.dwSize := sizeof(THREADENTRY32);

  If Thread32First(ThreadSnap, Te32) = True Then
  Begin
    Repeat;
      If Te32.th32OwnerProcessID = PID Then
      Begin
        NewThread := OpenThread(THREAD_SUSPEND_RESUME, False, Te32.th32ThreadID);

        If F_Pause = True Then
        Begin
          SuspendThread(NewThread);
        End
        Else
        Begin
          ResumeThread(NewThread);
        End;
       
        CloseHandle(NewThread);
      End;

    Until Thread32Next(ThreadSnap, Te32) = False;
    Result := True;
  End
  Else
  Begin
    Result := False;
  End;

  CloseHandle(ThreadSnap);
end;
Aufruf:

Delphi-Quellcode:
//Um Prozess zu pausieren:
PauseProcess(2940, True);
//Um Prozess fortzusetzen:
PauseProcess(2940, False);

brechi 28. Mai 2009 15:29

Re: Fremdes Programm/Anwendung pausieren?
 
Hm stimmt, mit den Threads lag ich falsch.

Trotzdem suspended ihr doch den Prozess nicht, wenn mind ein ThreadCounter > 1 ist. Also müsste man jeden Thread so oft "Suspenden" bis der counter -1 ist und die Anzahl merken. Beim restoren die selbe Anzahl wieder "Resumen".

Bei dem Result Parameter sollte auch eher ein AND stehen. Ansonsten würde ich das auch so machen.

Fridolin Walther 28. Mai 2009 15:50

Re: Fremdes Programm/Anwendung pausieren?
 
Zitat:

Zitat von brechi
Bei dem Result Parameter sollte auch eher ein AND stehen. Ansonsten würde ich das auch so machen.

Stimmt, ist korrigiert. Dankeschön :). Hatte das nur schnell runtergeschrieben und wollte den Rückgabeparameter erst auch ganz weglassen. Da es noch einige andere Probleme gibt und mir auf die Schnelle kein Weg eingefallen ist, wie man den Rückgabewert schön ermitteln könnte ohne eine weitere Hilfsvariable. Werd das bei Gelegenheit wenn ich Zeit hab noch mal etwas schöner machen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:42 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz