AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi 1. Instanz nach vorn bringen, wenn 2. geöffnet wird - fensterunabhängig!
Thema durchsuchen
Ansicht
Themen-Optionen

1. Instanz nach vorn bringen, wenn 2. geöffnet wird - fensterunabhängig!

Ein Thema von RSE · begonnen am 4. Mär 2013 · letzter Beitrag vom 6. Mär 2013
Antwort Antwort
RSE

Registriert seit: 26. Mär 2010
254 Beiträge
 
Delphi XE Enterprise
 
#1

1. Instanz nach vorn bringen, wenn 2. geöffnet wird - fensterunabhängig!

  Alt 4. Mär 2013, 15:00
Hallo,

unser Programm darf nur 1x geöffnet werden. Dazu verwenden wir ein benanntes Mutex-Objekt (Win32-API-Call CreateMutex). Für den Fall, dass ich von GetLastError = ERROR_ALREADY_EXISTS zurückbekomme, möchte ich gerne die erste Instanz des Programms nach vorne holen - unabhängig davon, was da gerade für Fenster offen sind. Allerdings scheitere ich schon daran, die Prozess-ID oder irgendetwas anderes von dem Prozess, der das Mutex-Objekt besitzt (also die erste Instanz des Programms), herauszubekommen. Der Grund ist einfach meine Unkenntnis der Win-API. Wahrscheinlich verwende ich nicht die richtigen Suchbegriffe.

Ich möchte nicht nach einem Fenster mit einem bestimmten Caption suchen, dann würde ich es lieber lassen. Allerdings bin ich mir sicher, dass es durchaus elegantere Wege gibt als diesen.
"Seit er seinen neuen Computer hat, löst er alle seine Probleme, die er vorher nicht hatte."
  Mit Zitat antworten Zitat
mjustin

Registriert seit: 14. Apr 2008
3.005 Beiträge
 
Delphi 2009 Professional
 
#2

AW: 1. Instanz nach vorn bringen, wenn 2. geöffnet wird - fensterunabhängig!

  Alt 4. Mär 2013, 15:04
Für den Fall, dass ich von GetLastError = ERROR_ALREADY_EXISTS zurückbekomme, möchte ich gerne die erste Instanz des Programms nach vorne holen - unabhängig davon, was da gerade für Fenster offen sind.
Die Jedi Code Library enthält eine hilfreiche Klasse (TJclAppInstances), die diese Funktion implementiert. Als Basis für eigenen Code ist diese Klasse eventuell einen Blick wert (Open Source).
Michael Justin
  Mit Zitat antworten Zitat
CCRDude

Registriert seit: 9. Jun 2011
677 Beiträge
 
FreePascal / Lazarus
 
#3

AW: 1. Instanz nach vorn bringen, wenn 2. geöffnet wird - fensterunabhängig!

  Alt 4. Mär 2013, 15:45
Fenster kann man nicht nur anhand der Caption, sondern auch anhand des Klassennamens suchen, das ist schon deutlich eindeutiger.

Ansonsten: ne Pipe? Darüber können ggfls. auch gleich Parameter übermittelt werden (etwa wenn die zweite Instanz mit nem Dateinamen zum Öffnen als Parameter gestartet wird - soll dann ja die erste Instanz diese Datei wahrscheinlich öffnen), und die erste Instanz kann sich einfach selbst wieder in den Vordergrund holen.
  Mit Zitat antworten Zitat
RSE

Registriert seit: 26. Mär 2010
254 Beiträge
 
Delphi XE Enterprise
 
#4

AW: 1. Instanz nach vorn bringen, wenn 2. geöffnet wird - fensterunabhängig!

  Alt 4. Mär 2013, 16:31
@mjustin:
TJclAppInstances war prinzipiell eine gute Idee zum Nachforsten, aber ich steige da überhaupt nicht durch. Da wird irgendetwas mit File Mapping gemacht - kenne ich bisher nicht, scheint aber eine gemeinsame Datei vorauszusetzen, die von mehreren Prozessen gleichzeitig benutzt wird und in der dann Informationen gesammelt werden. Das Ganze erscheint mir zu aufwendig für meinen Einsatzzweck.

@CCRDude:
Von Pipes habe ich bisher auch nichts gewusst, aber folgendes scheint ein einfacher und zielführender Weg zu sein:
Bei Programmstart versuche ich eine Pipe mit dem Parameter FILE_FLAG_FIRST_PIPE_INSTANCE zu erstellen. Gelingt das, so ist es die erste Programminstanz. Schlägt das fehl, so verbinde ich zu der bestehenden Pipe und informiere die erste Instanz, dass sie sich nach vorn bringen soll (Application.BringToFront) und beende die aktuelle (zweite) Instanz.

Ich werde mich morgen mit dem Handling der Pipes genauer auseinandersetzen, habe jetzt nur überflogen, was Pipes sind Wenn dabei für mich unlösbare Probleme auftreten, melde ich mich nochmal, ansonsten: Danke für die Lösung!
"Seit er seinen neuen Computer hat, löst er alle seine Probleme, die er vorher nicht hatte."
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.051 Beiträge
 
Delphi 12 Athens
 
#5

AW: 1. Instanz nach vorn bringen, wenn 2. geöffnet wird - fensterunabhängig!

  Alt 4. Mär 2013, 16:40
Der Ansatz, daß sich die erste Instanz selbst in den Vordergrund bringt, wird in den meisten Fällen schief gehen. Windows erlaubt es nämlich i.A. nicht, daß ein Prozess sich selbst in den Vordergrund drängelt (da könnte ja jeder kommen). Dies ist unter anderem aber dem Prozess erlaubt, der gerade gestartet wurde - also der zweiten Instanz. Ich empfehle daher, das so zu implementieren, daß doch die zweite Instanz die erste in den Vordergrund holt.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
RSE

Registriert seit: 26. Mär 2010
254 Beiträge
 
Delphi XE Enterprise
 
#6

AW: 1. Instanz nach vorn bringen, wenn 2. geöffnet wird - fensterunabhängig!

  Alt 5. Mär 2013, 11:27
Also das mit den Pipes habe ich jetzt implementiert. Selbst ohne Kommunikation durch die Pipes kann ich folgendes erreichen:
  • Nur die Erste Instanz startet normal - nur dann ist CreateNamedPipe mit FILE_FLAG_FIRST_PIPE_INSTANCE erfolgreich - Jede weitere Instanz erkennt, dass bereits eine andere Instanz läuft und kann darauf reagieren
  • Eine zweite Instanz kann die erste Instanz folgendermaßen ermitteln: Sie verbindet sich mit CreateFile mit den Parametern GENERIC_READ und OPEN_EXISTING auf die Pipe und erhält das Pipe-Handle. Damit kann sie mittels GetNamedPipeServerProcessId die Prozess-ID der ersten Instanz ermitteln
  • Eine dritte Instanz braucht keine Meldung mehr ausgeben, dass bereits eine Instanz läuft, da das bereits die zweite Instanz tut. Dieser Fall könnte z.B. eintreten, wenn bereits eine Instanz hinter anderen Fenstern verborgen läuft und das Programm ungeschickt gleich mehrfach geöffnet wird. Dieser Fall wird als Nebeneffekt erkannt, wenn das Verbinden auf die bestehende Pipe nicht gelingt (weil Instanz 2 bereits verbunden ist). Das Programm kann in diesem Fall ohne weitere Handlungen beendet werden.
Offen bleibt also jetzt nur noch das In-den-Vordergrund-bringen der ersten Instanz durch die zweite Instanz. Dazu benötige ich offenbar ein Fenster-Handle der ersten Instanz, welches ich dann an SetForegroundWindow übergeben kann. Gefunden habe ich bei einer ersten Suche die GetGUIThreadInfo Funktion (benötigt die Thread-ID, welche man mittels der Prozess-ID ermitteln können sollte), welche mir eine GUITHREADINFO structure mit dem Handle des im Thread aktiven Windows liefert. Ist das ein guter Ansatz, oder gibt es bessere/bevorzugenswertere?

Ich sehe folgende Probleme incl. Lösungen bei meinem Ansatz:
  • Der Zielprozess hat wahrscheinlich mehrere Threads. In diesem Fall würde ich alle Threads durchsuchen, bis ich einen finde, der ein aktives Fenster besitzt und dieses in den Vordergrund bringen.
  • Zwischen der Ermittlung des aktiven Fensters und dem Aufruf/Umsetzung von SetForegroundWindow könnte das Fenster wieder verschwunden sein (Aufruf von Hide), falls es sich dummerweise gerade um mein "Bitte warten Sie, bis die lange Operation beendet wurde"-Fenster handelt. Ich nehme an, dass SetForegroundWindow in diesem Fall einen entsprechenden Rückgabewert liefert, damit ich den Vorgang auf einem neuen aktiven Fenster wiederholen kann.

So, jetzt habe ich euch erstmal mit aktuellen Infos versorgt und werde mittagessen gehen. Wenn bis danach keine Einwände gegen das Vorgehen gepostet wurden, werde ich die Umsetzung dann angehen

Mahlzeit!
"Seit er seinen neuen Computer hat, löst er alle seine Probleme, die er vorher nicht hatte."
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:22 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz