Delphi-PRAXiS
Seite 1 von 2  1 2   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Andere instanz beenden (https://www.delphipraxis.net/198119-andere-instanz-beenden.html)

MyRealName 4. Okt 2018 21:47

Andere instanz beenden
 
Also nehmen wir mal an, dass mein Programm nicht nachvollziehbar auf einem Rechner beim Beenden immer mal gern im Speicher "hängenbleibt", aber unsichtbar (man sieht es nur im Task Manager). Leider ist da dann auch UniDAC der Meinung, Firebird noch nichts zu sagen, dass wir gehen, die Verbindung also offen bleibt... Das verursacht dann, dass mein Programm annimmt, dass das andere Programm noch da ist. Wenn dann zum Bsp ein Dokument gelockt ist, dann wird das nicht freigegeben, da die Verbindung des locks noch da ist.

Gibt es da eine Möglichkeit, wie beim Task Manager, diese Programm-Instanz von Delphi aus zu schliessen ? Einfach ein WM_CLOSE dürfte nicht gehen, weil scheinbar kann das Programm auf diesen PC nicht einfach runterfahren und ein WM_CLOSE macht ja genau das. Ich kann es auch nicht nachvollziehen, warum und wann es hängenbleibt, es ist sporadisch und bisher nur euf einem Rechner zu beobachten.

Danke schonmal

Luckie 4. Okt 2018 22:26

AW: Andere instanz beenden
 
Du solltest die Ursache finden und nicht an den Symptomen rumdoktern. da du aber nicht näher schreibst, was dein Programm macht, ist es schwierig dir zu helfen.

Beendest du in WM_CLOSE auch alle laufenden Threads? Das könnte ein Grund sein.

Schließt du die offenen Datenbankverbindungen korrekt?

KodeZwerg 4. Okt 2018 22:37

AW: Andere instanz beenden
 
Auf den Thread Titel bezogen, füge
Delphi-Quellcode:
TerminateOtherInstances;
dem
Delphi-Quellcode:
OnFormCreate
zu.
Delphi-Quellcode:
procedure TForm1.TerminateOtherInstances;
var
  szClass : pchar;
  sTitle : string;
  h      : THandle;

begin
  sTitle := Application.Title;
  GetMem(szClass, 256);
  GetClassName(Application.Handle, szClass, 255);
  Application.Title := 'Dummy Caption';

  h := FindWindow(szClass, pchar(sTitle));
  while h <> 0 do
  begin
    PostMessage(h, WM_QUIT, 0, 0);
    Application.ProcessMessages;
    h := FindWindow(nil, pchar(sTitle));
  end;

  Application.Title := sTitle;
  FreeMem(szClass, 256);
end;
edit
Hinweis: Das funktioniert nur für Applikationen die immer den gleichen Application.Title besitzen!

Luckie 4. Okt 2018 22:58

AW: Andere instanz beenden
 
Öhm. Also das ist doch Murks. Ein zweites Programm zu schreiben, weil sich das erste nicht richtig beendet.

KodeZwerg 4. Okt 2018 23:30

AW: Andere instanz beenden
 
Ich Verstehe Dich da gerade nicht.
Was ich meinte war, in der Applikation wo man sicherstellen möchte das seine App nur einmal, undzwar frisch, geladen ist, da in FormCreate die "TerminateOtherInstances" Anweisung rein, fertig.
Ab nun sollte es nurnoch einmal diese Applikation geben.
Oder eine Mutex Abfrage, oder oder oder, gibt ja viele Möglichkeiten so was zu realisieren, ich zeigte halt eine davon, wenn die falsch war tuts mir leid.

MyRealName 4. Okt 2018 23:51

AW: Andere instanz beenden
 
Kein 2. Programm, sondern das erste soll prüfen, ob eine instanz hängen geblieben ist.
Ist natürlich keine schöne Lösung, aber ich kann das halt nicht nachvollziehen, mein log ist da schon aus und es passiert nur auf einem Kundenrechner, der 1000km weg ist

MyRealName 4. Okt 2018 23:55

AW: Andere instanz beenden
 
Zitat:

Zitat von KodeZwerg (Beitrag 1414943)
Ich Verstehe Dich da gerade nicht.
Was ich meinte war, in der Applikation wo man sicherstellen möchte das seine App nur einmal, undzwar frisch, geladen ist, da in FormCreate die "TerminateOtherInstances" Anweisung rein, fertig.
Ab nun sollte es nurnoch einmal diese Applikation geben.
Oder eine Mutex Abfrage, oder oder oder, gibt ja viele Möglichkeiten so was zu realisieren, ich zeigte halt eine davon, wenn die falsch war tuts mir leid.



Ist schon richtig, es sollte eine "TerminateOtherInstances" Anweisung werden, den Mutex habe ich schon, weil es ein "Point Of Sale" ist und es keinen Sinn macht, den mehrmals am Laufen zu haben. Da der auch autonom ist, also wenn man Netzwerk oder internet ausfällt, das POS einfach weiterarbeitet und Rechnungen dann synchronisiert, wenn das Netz wieder da ist, lässt man das auch nicht in einem Terminal Server laufen :)

Delphi.Narium 5. Okt 2018 09:50

AW: Andere instanz beenden
 
Zitat:

Zitat von KodeZwerg (Beitrag 1414934)
Delphi-Quellcode:
procedure TForm1.TerminateOtherInstances;
var
  szClass : pchar;
  sTitle : string;
  h      : THandle;

begin
  sTitle := Application.Title;
  GetMem(szClass, 256);
  GetClassName(Application.Handle, szClass, 255);
  Application.Title := 'Dummy Caption';

  h := FindWindow(szClass, pchar(sTitle));
  while h <> 0 do
  begin
    PostMessage(h, WM_QUIT, 0, 0);
    Application.ProcessMessages;
    h := FindWindow(nil, pchar(sTitle));
  end;

  Application.Title := sTitle;
  FreeMem(szClass, 256);
end;

Das hat aber einen Haken: Wenn das zu beendende Programm nicht (mehr) auf WM_QUIT reagiert, bleibt auch jede weitere Instanz "hängen". Eventuell in der Schleife mitzählen und nach X Versuchen raus aus der Schleife, mit 'ner entsprechenden Fehlermeldung.

Und ggfls. in der Schleife eine Pause einfügen, damit die andere Instanz Zeit zum Beenden bekommt.

Eventuell ungefähr sowas?
Delphi-Quellcode:
function TForm1.TerminateOtherInstances(iVersuche : Integer; sMeldung : String) : Boolean;
var
  szClass : pchar;
  sTitle : string;
  h      : THandle;
  iCount : Integer;
begin
  sTitle := Application.Title;
  iCount := 0;
  GetMem(szClass, 256);
  GetClassName(Application.Handle, szClass, 255);
  Application.Title := 'Dummy Caption';

  h := FindWindow(szClass, pchar(sTitle));
  Result := h = 0;
  while not Result and (iCount < iVersuche) do
  begin
    PostMessage(h, WM_QUIT, 0, 0);
    Application.ProcessMessages;
    iCount := iCount + 1;
    Sleep(1000);
    h := FindWindow(nil, pchar(sTitle));
    Result := h = 0;
  end;
  if iCount >= iVersuche then begin
    MessageDLG(sMeldung,mtError,[mbOk],0);
  end;
  Application.Title := sTitle;
  FreeMem(szClass, 256);
end;

DieDolly 5. Okt 2018 09:51

AW: Andere instanz beenden
 
Zitat:

Kein 2. Programm, sondern das erste soll prüfen, ob eine instanz hängen geblieben ist.
Das würde ich direkt in die DPR schreiben damit die Prüfung stattfindet noch bevor irgendein Formular erzeugt werden konnte (Ressourcensparender und so ...).

KodeZwerg 5. Okt 2018 10:19

AW: Andere instanz beenden
 
Da er Mutex bereits einsetzt und ich DieDolly Recht gebe (so mach ichs auch hin und wieder) frage ich mich was beim TE damit nicht funktioniert, Handle zum präProzess sollte man ja Dank Mutex ausgewerten haben.

Danke Delphi.Narium, ich werde meine CodeLib anpassen, das hilft!:thumb:

edit
habe code entfernt der das neu gestartete auch mit abschießt, sorry


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:25 Uhr.
Seite 1 von 2  1 2   

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