Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi PID eines prozesses merken, Anwendung ähnlich Taskleiste (https://www.delphipraxis.net/137926-pid-eines-prozesses-merken-anwendung-aehnlich-taskleiste.html)

LokutusvB 31. Jul 2009 09:05


PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Guten Morgen,

ich habe ein Programm geschrieben, mit dem ich einfach mittels
Delphi-Quellcode:
wh := ExecuteFile(xdir+EXE_NAME, '', xdir);
ein anderes Programm starte. Durch eine Auswertung prüfe ich, wie oft das Programm gestartet wurde und lasse so 3 gleichzeitige Instanzen zu. Das passiert zur Zeit über nur einen Button. Nun möchte ich das Programm ähnlich wie die Taskleiste gestalten. Es soll nun 3 Buttons geben. Jeder dieser Buttons startet eine Instanz des Programmes. Ist diese bereits gestartet, soll das Fenster des Programmes automatisch wieder in den Vordergrund gelangen. Und hier stehe ich jetzt auf dem Schlauch und weiss nicht recht, wie ich das realisieren kann :(. Wie kann ich bei dem Start eines externen Programmes die PID merken um das Programm später wieder in den Vordergrund zu bekommen bzw. maxmieren zu können?

Zusatz:
Was mir spontan einfällt ist:
Ersten Prozess starten, PID auslesen
Zweiten Prozess starten, PIDs auslesen und vergleichen, neue zuordnen und merken
Dritten Prozess starten und das gleiche Spiel.

Meine Hoffnung ist jedoch, daß dieser Vorgang mit Boardmitteln bereits viel einfacher möglich ist.

ExecuteFile ist ähnlich dem OpenFile.

Zusatz1:
Ich konnte ExecuteAndWait finden. Was ist der bessere Weg, für jeden der 3. Button einen Trhead anlegen und starten, der nach diesem prinzip arbeitet oder sollte ich doch so vorgehen wie oben beschrieben?

r29d43 31. Jul 2009 14:07

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Wieso brauchst du die PID um ein Programm in den Vordergrund zu bekommen? Die normale Handle (mit "FindWindowEx" zu suchen und zu finden) genügt doch auch. Dann als Parameter der API-Funktion "SetForegroundWindow".

LokutusvB 31. Jul 2009 14:30

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Das ich die PID unbedingt benötige, davon bin ich noch heut morgen ausgegangen, siehe erste Zeilen meines Beitrages, da ich die Exe-Datei mittels ShellExecute starte. Da jedoch 3 mal das gleiche Programm gestartet wird, nützt mir da ein Fesnter-Handle nicht so viel. Deswegen meine Lösungsansätze.

DeddyH 31. Jul 2009 14:33

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Die ProcessID bekommst Du mit ShellExecuteEx oder CreateProcess.

r29d43 31. Jul 2009 15:03

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Zitat:

Zitat von LokutusvB
...Da jedoch 3 mal das gleiche Programm gestartet wird, nützt mir da ein Fesnter-Handle nicht so viel...

Wieso das denn? Erklär mal bitte ein bissl genauer.

Es geht doch imo nur um das Hochholen jeweils eines der Progs in den Vordergrund. Und dafür taugt eine normale Handles jedenfalls allemal. Wenn Du die Handle vom ersten Prog an immer gleich nach dem Start suchst und dann abspeicherst, kannst Du ohne Probleme per FindWindowEx auch die Handel eines dann jeweils weiteren gleichen Programms finden und, wie schon gesagt, dieses später dann per z.B.

SetForegroundWindow(HandleProg3);

in den Vordergrund schaffen.

LokutusvB 3. Aug 2009 08:24

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Doch, du hast Recht. Das wäre durchaus machbar. Das ist dann genau das Prinzip, was ich anfangs ansetzten wollte, nun aber mit dem Handle.

Da mir jedoch im Laufe der Überlegungen und Nachforschungen noch die 2. Variante ins Auge gefallen ist, ist jetzt die Frage, welche der beiden Varianten die bessere bzw. elegantere Lösung ist. Suche ich nach dem Start nach einem Handle, vergleiche, speichere oder aber rufe wieder in den Vordergrund oder arbeite ich für jeden der 3. Buttons mit einem Thread und benutzte ExecuteAndWait? Für mich sieht die 2. Möglichkeit nach der Möglichkeit aus, die funktioneller ist. Oder irre ich mich?

r29d43 3. Aug 2009 09:49

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Zitat:

Zitat von LokutusvB
...oder arbeite ich für jeden der 3. Buttons mit einem Thread und benutzte ExecuteAndWait? Für mich sieht die 2. Möglichkeit nach der Möglichkeit aus, die funktioneller ist.

Nö, wieso denn mit einem Thread? Das ist doch viel zu aufwendig für so eine einfache Sache. Alles was Du event. noch brauchst ist ein Timer, mittels dem Du dann z.B. jede Sekunde neu ermittelst ob ein jeweiliges dieser Programme (zu dem du vorher ein Handle gefunden und abgespeichert hast) immer noch läuft (das heißt, ob diese Handle per FindWindowEx immer noch genauso zu finden ist). Und wenn das nicht der Fall ist, dann muss es wohl beendet worden sein. Dann lädst Du in die da dazugehörende Handle-Variable eine 0 (ist dann auch als Flag brauchbar, dass diesem Button aktuell kein laufendes Programm zugeordnet ist) und machst event. auch noch den Button dementsprechend erkennbar (z.B. durch eine andere Caption)...

LokutusvB 3. Aug 2009 13:18

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
So langsam steige ich durch dieses Handle-Thema.

Würde in diesem Fall nicht auch FindWindow ausreichen, was mir ja das Handle zurückliefert? Gibt das alle gefundenen Handle zurück oder nur das zuerst gefunde?

Mit FindWindowEx kann ich ein spezielles Fenster bzw. Handle suchen, wenn ich das richtig verstehe. Allerdings funktioniert das bei mir auch noch nicht so recht.

Das Handle bekomme ich mittels:
Delphi-Quellcode:
twH1 := FindWindow('abc', 'xyz');
Egal, wie ich nun abfrage:
Delphi-Quellcode:
twH2 := FindWindowEx(0, twH1, 'abc', 'xyz');
oder
Delphi-Quellcode:
twH2 := FindWindowEx(twH1, 0, 'abc', 'xyz');
Alle beide male kommt 0 raus. Erst wenn ich an beiden Stellen eine 0 einsetze, bekomme ich das richtige Handle zurück. Das nützt mir ja aber nix, da ich genau nach den bereits vorhandenen Handles suchen muß und nich nach irgend einem. Was mache ich noch falsch? Eigentlich müßte das doch so gehen?

Zusatz: Wieso funktioniert
Delphi-Quellcode:
if (FindWindowEx(0, 0, 'abc', 'xyz') = twH1)
nicht, jedoch aber
Delphi-Quellcode:
if (twH2 = twH1)
?

r29d43 3. Aug 2009 16:26

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
FindWindow gibt immer nur das zuerst gefundene Handle zurück. Und weil das so ist, ist das für dich hier auch nicht geeignet ...eben weil Du immer nach Windows suchen musst, die bzgl. ihres Class-Namens und bzgl. ihres Title-Textes quasi zueinander identische Windows sind.

Mit FindWindowEx geht das aber. Dabei muss der erste Parameter immer die Null sein, was soviel heißt wie: Es werden immer Windows gesucht, die gerade auf dem Desktop laufen ...wobei für alle diese auf dem Desktop laufenden Windows dann gilt, dass sie damit auch quasi Child-Windows dieses Desktops sind. Ergo wirst Du mit

Prog1 := FindWindowEx(0,0,ClassName,TitleText);

dann auch das erste von dir gesuchte Window finden. Und für die Suche nach dem zweiten solchen Window musst Du jetzt einfach nur hinter diesem ersten Fund mit der Suche weitermachen, also:

Prog2 := FindWindowEx(0,Prog1,ClassName,TitleText);

usw. usf...

Und genauso suchst Du dann natürlich auch immer nach einer bestimmten Handle, von der Du z.B. wissen willst, ob es sie denn überhaupt noch gibt (bzw. ob das dazugehörende Programm noch läuft)...

LokutusvB 4. Aug 2009 12:28

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Ok, danke für deine Hilfe und die ausführlichen Erklärungen! :)

So wie du es beschrieben hast, funktioniert das Ganze sehr gut. Ich kann so nun alle 3 Programme bestimmen und die maximale Anzahl der Programme trotzdem auf 3 beschränken. Nun geht es an das in den Vordergrund holen der haupt- bzw. geöffneten Unterfenster.

Ich danke dir für deine Hilfe!

LokutusvB 5. Aug 2009 07:58

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Ich hoffe ich nerve nicht :(, aber die Probleme gehen weiter.

Leider konnte ich im Netz nichts finden. Gibt es eine einfache Möglichkeit, alle Fensterhandle zu ermitteln und z.B. in einer TStringList zu speichern?

ich habe große Probleme, nach dem Fensterhandle zu suchen, wenn das Programmfenster des externen Programmes minimiert ist, das Hauptprogramm mit den Buttons den Fokus hat oder aber ein Unterprogramm des externen Programmes geöffnet ist.

Ich dachte beim Unterprogramm könnte ich einfach mittels
aktHndl := GetTopWindow(GetDesktopWindow);
wTmpH := GetParent(aktHndl);
das Handle des externen Hauptfensters ermitteln, aber weit gefehlt. Es liefert mir ständig ein anderes Handle zurück. Und im falle des Fokus auf meinen "Taskmamager" bin ich mir auch nicht ganz sicher, ob ich so einfach nach dem handle des externen Hauptfensters suchen kann, was ist z.B. wenn es minimiert oder gar "unsichtbar" ist, da ein Unterprogramm aktivi ist, was wiederum vielleicht minimiert ist?

Deswegen wäre es mir an dieser Stelle lieb, wenn ich eine Möglichkeit hätte, alle aktuellen Fensterhandles des Systems zu ermitteln um dort dann einfach zu suchen, ob mein Handle mit von der Partie ist.

DeddyH 5. Aug 2009 08:11

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Spontan fällt mir da MSDN-Library durchsuchenEnumWindows ein.

LokutusvB 5. Aug 2009 08:51

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Danke, zusätzlich konnte ich noch EnumWindows & Co gekapselt finden. Das sollte weiter helfen.

LokutusvB 5. Aug 2009 10:05

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Der Fehler liegt bei mir :? .

Durch das Probieren mit EnumWindows bin ich drauf gekommen, daß die Handle schon noch existieren, FindWindowsEx jedoch 0 zurückliefern muß, da ich ja immer noch bei der Suche nach dem speziellen Fenstername gesucht habe. Nehme ich den raus, wird das Handle gefunden, auch wenn ein anderes Fenster aktiv ist bzw. ein Unterpgrogramm und der Timer kann nun entsprechend reagieren.

Durch die EnumWindows-Funktionen jedoch spare ich mir viel Auswertungskram und kann direkt die Liste durchsuchen.

LokutusvB 5. Aug 2009 14:15

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Eine Frage:

ich arbeite nun mit der EnumWindowsUnit, wie von mir schon verlinkt.

Nun kommt es vor, das ein externes Programm wiederum ein anderes externes Programm startet. Ist das der Fall, sieht man zwar in der Windows-Taskleiste unten noch den Eintrag, dieser ist aber disabled, bei einem Klick passiert nichts.

EnumWindows bzw. EnumTopLevelWindows aus der Unit kann dieses Fenster bzw.Handle nicht finden. Versuche ich das selbe mit FindWindowEx, wird das Handle jedoch erkannt, also ist da auch was da. Kann ich die EnumWindowsUnit irgendwie erweitern, das sie inaktive jedoch laufende Programme bzw. Fenster auch erkennt? So langsam schlaucht mir das echt zu sehr. Wenn die Probleme so weiter gehen, werde ich das wohl doch mit Threads lösen :(.

LokutusvB 6. Aug 2009 10:54

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Endlich funktioniert mal etwas und liefert mir sogar die passenden Handle zurück. Kann ich das noch irgendwie optimieren?

Delphi-Quellcode:
function TFormMainDlg.getTWHandle: HWND;
var
  tmpTW: HWND;
begin
  Result := 0;
  tmpTW := FindWindowEx(0, 0, 'abc', 'xyz');
  if (tmpTW = 0) then Exit;
  if (tmpTW = twH1) then begin
    tmpTW := FindWindowEx(0, twH1, 'abc', 'xyz');
    if (tmpTW = 0) then Exit;
    if (tmpTW = twH2) then begin
      tmpTW := FindWindowEx(0, twH2, 'abc', 'xyz');
      if (tmpTW = 0) then Exit;
      Result := tmpTW;
      Exit;
    end;
    if (tmpTW = twH3) then begin
       tmpTW := FindWindowEx(0, twH3, 'abc', 'xyz');
      if (tmpTW = 0) then Exit;
      Result := tmpTW;
      Exit;
    end;
  end;
  // analog twH2 und 3
  Result := tmpTW;
end;

r29d43 6. Aug 2009 12:21

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
ungefähr so insgesamt?

Delphi-Quellcode:
function getTWHandle(twH1,twH2,twH3 : THandle) : THandle;
function checkHandle(hToCheck : THandle) : boolean;
begin // muss true sein wenn hToCheck nicht schon in Handle123 registriert ist
  result := (twH1 <> hToCheck) and (twH2 <> hToCheck) and (twH3 <> hToCheck);
end;
begin
  result := 0;
  repeat
    result := FindWindowEx(0,result,'Notepad','Unbenannt - Editor');
  until (result = 0) or checkHandle(result);
end;
(Ich checkte das mal schnell für drei gleiche NotePad-Aufrufe).

LokutusvB 6. Aug 2009 12:36

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Ok, dann warte ich so lange^^.

Ist es eigentlich egal, ob man THandle oder HWND vereinbart?

r29d43 6. Aug 2009 12:46

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Ich schrieb "checkte", das ist "past tens", sozusagen auch die Vergangenheitsform des Verbes *g*.


Zitat:

Zitat von LokutusvB
Ist es eigentlich egal, ob man THandle oder HWND vereinbart?

imo müsste das eigentlich egal sein.

LokutusvB 6. Aug 2009 12:52

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Oh, jetzt wo du es sagst, da habe ich doch wirklich das "t" überlesen *g*.

Na dann danke schön für die Optimierung :).

LokutusvB 7. Aug 2009 12:19

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Was mache ich, wenn SetForegroundWindow(handle) True zurückliefert, obwohl es zur zeit gar kein Fenster des Handles gibt, was in den Vordergrund gesetzt werden kann? Wieso wird trotzdem True zurückgegeben? So wird mir doch jegliche Möglichkeit der Auswertung genommen.

Der Grund ist ein 2. geöffnetes externes Programm das 1. externen Programmes, welches ich aus meiner "Taskleiste" heraus starte. Öffne ich aus diesem externen Programm wiederum ein externes Programm, wird das durch mein Programm geöffnete Programm in die Windows-Taskleiste minimiert und reagiert auf nichts mehr, das neue externe geöffnete Programm ist aktiv. Möchte ich das nun in den Vordergrund holen bei Druck auf den Button, passiert natürlich nichts, da ich nach dem Handle des 1. Programmes frage. Und dummerweise kann ich nichts weiter auswerten, da SetForegroundWindow(handle) True liefert, obwohl nix in den Vordergund gesetzt wurden ist.

Hat jemand eine Idee, wie ich das Problem lösen kann?

LokutusvB 10. Aug 2009 14:57

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Und noch ein Punkt:
Habe ich irgendwie die Möglichkeit herauszufinden, welches Programm ein anderes gestartet hat? Wenn ein externes Programm ein anderes externes Programm startet, dann läuft das ja nicht mehr über ChildHandle, oder doch?

r29d43 10. Aug 2009 22:00

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Zitat:

Zitat von LokutusvB
Habe ich irgendwie die Möglichkeit herauszufinden, welches Programm ein anderes gestartet hat?

So ohne weiteres nicht. Wenn Du allerdings die Programme miteinander kommunizieren läßt (die dann natürlich auch wieder von dir geschrieben sein müssen), dann sollte das schon gehen. Angenommen ein externes Programm A startet ein anderes externes Programm B, dann musst Du nur dafür sorgen, dass Programm A dir (sprich: deinem ursprünglichen Programm ...das mit seiner eigenen Taskbar) dieses auch mitteilt, ..also dass es jetzt nämlich ein weiteres Programm starten wird. Und als nächstes müssten diese externen Programme auch noch die Fähigkeit haben, das diesem ursprünglichen Programm ebenfalls mitzuteilen ..also dass es (= externes Programm B) eben gerade gestartet wurde.

Gut bewerkstelligen ließe sich das z.B. mit dem Window-Message-System. Mittels der RegisterWindowMessage-APIFunktion können sich alle daran beteiligte Programme dafür zuerst jeweils eine dazu bestimmte WindowMessage erzeugen lassen und darüber dann so eine Kommunikation abwickeln. (Die Handle deines ursprünglichen Programms wissen diese externen Programme indem sie danach per FindWindowEx suchen oder sie ihnen immer wieder mittels "Parameter" der ShellExecute-Funktion mitgegeben wird). Im WParameter einer solchen WindowMessage stände dann z.B. immer dasjenige ID-Wort, das die jeweilige Situation identifiziert, und im LParameter die Handle des Absender-Programms. Schließlich könntest Du dir von diesen externen Progs auch noch mitteilen lassen, wenn sie beendet werden, und dann bräuchtest du überhaupt nie nach irgendwelchen ihrer Handles zu suchen, sondern Du bekämst alle diesbezüglichen Infos von ihnen selbst immer gleich schön zugeschickt.

(Alternativ zum Window-Message-System könnte man eine solche Kommunikation übrigens auch mit den Indy-Komponenten TIdTCPClient und TIdTCPServer abwickeln).

Zitat:

Zitat von LokutusvB
Wenn ein externes Programm ein anderes externes Programm startet, dann läuft das ja nicht mehr über ChildHandle, oder doch?

Nein, so ein externes Programm ist dann kein Child-Window des Progs das es gestartet hat. (Aber sehr wohl wieder ein direktes Child-Window des Desktops)

Event. noch eines: Bei irgendwelchen neuen Fragen sollte man besser auch immer einen neuen Thread eröffnen ...weil ansonsten die Chancen eine Antwort zu bekommen doch immer kleiner werden je länger und spezieller so ein Thread wird.

LokutusvB 11. Aug 2009 07:02

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Guten Morgen,

und ich dachte eben, da es ja trotzdem um das gleiche Ausgangsthema ist, überfulte ich das Forum nicht jedes mal mit einem neu eröffneten Thema. Vielleicht kann das ja ein Moderator richten, wenn er meint daß das besser ist.

Nein, genau das ist mein Problem. Diese Taskbar ist von mir, und die möglichen Endprogramme. Das Programm, was sich aus der Taskbar öffnen lässt, ist eben leider nicht von mir, deswegen habe ich diese Probleme hier und in anderen Diskussionen erläutert. Lässt sich das trotzdem irgendwie bewerkstelligen?

r29d43 11. Aug 2009 07:17

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Moin, moin,

das Programm mit der Taskbar und diese möglichen Endprogramme könnten dann ja immerhin schonmal miteinander kommunizieren.

...Und das Programm, was sich aus der Taskbar öffnen lässt, was macht das nochmal schnell in diesen Gesamtabläufen?

LokutusvB 11. Aug 2009 07:29

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Das ist eine Art CRM-Modul, was man dahingehend bearbeiten kann, daß es auch andere Programme öffnen und ausführen kann. Und das ist dann auch der für mich wichtige Teil, die Abarbeitung der externen Programme in meiner Taskbar. Dieses Modul minimiert sich beim Öffnen eines externen Programmes und ist disabled oder zumindest unsichtbar. Wird das externe programm beendet, wird dann auch automatisch wieder das Modul eingeblendet.

r29d43 11. Aug 2009 07:42

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
So groß scheint die Funktion von diesem CRM-Modul nicht zu sein. Im Zweifelsfall kannst Du so eine Funktion also auch selbst schreiben, in Form von zwei/drei Procedures in deinem ursprünglichen Programm. Dann hättest Du wenigsten die volle Kontrolle über diese ganzen Abläufe. Insgesamt wäre das wahrscheinlich ein nur geringer Aufwand, gemessen an den Vorteilen, die Du damit für dich erreichst.

LokutusvB 11. Aug 2009 08:04

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Nein, so ist es leider nicht. Ich habe nur die für mich relevante Funktionalität aufgezeigt. Das ganze ist schon ein komplizierte Datenbankanwendung mit Multiuserfunktionalität. Mit selbt schreiben ist da leider nichts.

r29d43 11. Aug 2009 08:10

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
Wenn nur diese wenigen Funktionen für dich relevant sind, dann kannst Du ja auf den ganzen Rest verzichten ..und dir eben nur diese wenigen Funktionen selbst schreiben.

LokutusvB 11. Aug 2009 12:49

Re: PID eines prozesses merken, Anwendung ähnlich Taskleiste
 
ja, stimmt schon, irgendwann reicht es dann auch.

Ich werde bewerkstelligen, das man diese externen Programme auch aus meiner Anwendung heraus starten kann und den Start aus dem Modul heraus verhindern. Das ist, glaube ich, der einfachste und zugleich sicherste Weg. Mit diesem Modul gibt es nichts außer Probleme. Ich zweifel schon bald an mir selbst :(, nichts der StandardWindows-Funktionen greift hier ordentlich.


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:22 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