AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Windows tötet Delphi-Anwendung noch vor Unit-Finalisierung
Thema durchsuchen
Ansicht
Themen-Optionen

Windows tötet Delphi-Anwendung noch vor Unit-Finalisierung

Ein Thema von Der schöne Günther · begonnen am 23. Dez 2015 · letzter Beitrag vom 24. Dez 2015
Antwort Antwort
Seite 1 von 2  1 2      
Der schöne Günther

Registriert seit: 6. Mär 2013
6.176 Beiträge
 
Delphi 10 Seattle Enterprise
 
#1

Windows tötet Delphi-Anwendung noch vor Unit-Finalisierung

  Alt 23. Dez 2015, 20:08
Es geht um das Herunterfahren bzw. Abmelden des Benutzers. Ich stelle hier grade fest dass beim Herunterfahren Code im finalization -Abschnitt einer Unit nicht ausgeführt wird. Wenn ich das Herunterfahren "fälsche" indem ich mir selbst einfach eine WM_ENDSESSION -Nachricht schicke beendet sich die VCL-Anwendung zwar auch, führt aber auch ordentlich alles im finalization-Abschnitt aus.

Mein kompletter Code sieht folgendermaßen aus:

Delphi-Quellcode:
procedure TForm3.FormCreate(Sender: TObject);
begin
   Application.HookMainWindow(wndProcHook);
end;

function TForm3.wndProcHook(var message: TMessage): Boolean;
begin
   Result := false;
   case message.Msg of
      WM_ENDSESSION: begin
         placefile('ZZzzz 1');
         sleep(5000);
         placefile('ZZzzz 2');
         Halt(0);
      end;
   end;
end;

initialization
finalization
   placeFile('unit finalization');
end.
placeFile(..) legt nur eine leere Datei im gleichen Verzeichnis wie die exe an.

Wenn ich das Herunterfahren "fälsche" erhalte ich die drei Dateien "ZZzzz 1", "ZZzzz 2" und "unit finalization". Melde ich mich richtig ab, fehlt das "unit finalization" einfach.

Ich habe keine Ahnung wie ich das debuggen könnte. Meine Vermutung: Irgendeine Unit-Finalisierung der VCL ist vor meiner dran. Dort drin werden wohl weiter kurz Messages abgearbeitet. Das ist tödlich, denn Windows nimmt so etas nach einem WM_ENDSESSION zum Anlass das Programm direkt abzuschießen.

Siehe hier: Once you return from the WM_ENDSESSION message, your process can be terminated at any time.


Es ist eine schwache Vermutung, aber die einzige die ich habe. Mein Ziel ist es, dass die Finalisierung aller Units ausgeführt wird und Windows meine Anwendung nicht vorher abschießt. Kann mir jemand helfen?
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

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

AW: Windows tötet Delphi-Anwendung noch vor Unit-Finalisierung

  Alt 23. Dez 2015, 21:27
Ich meine, die 5 Sekunden sind genau die Zeit, die Windows wartet, bis es eine Anwendung als unresponsive einfach killt.

Slightly OT: Den Hook kannst du dir sparen. Dies tut's auch:

    procedure wmEndSession(var Message: TMessage); message WM_ENDSESSION;
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#3

AW: Windows tötet Delphi-Anwendung noch vor Unit-Finalisierung

  Alt 23. Dez 2015, 22:03
Wenn du noch etwas zu erledigen hast, dann musst du das währen der WM_ENDSESSION Nachricht machen.

Nach dieser Nachricht kann alles passieren (z.B. Windows killt den Prozess).
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.650 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Windows tötet Delphi-Anwendung noch vor Unit-Finalisierung

  Alt 23. Dez 2015, 23:19
Und wenn du etwas erledigen musst, das länger dauert, musst du Windows das mitteilen. Du kannst dich entsprechend registrieren und wirst dann auch auf dem Herunterfahren-Bildschirm angezeigt in der Liste der Anwendungen, die das Herunterfahren blockieren.

Wir haben keinerlei wichtigen Code in finalization drin. Es gibt Startup- und Shutdown-Abläufe, die aber sämtlich innerhalb des begin..end des Projekts ablaufen. In finalization passieren nur noch Sachen, auf die wir keinen Einfluss haben (Delphi-Units, 3rd-Party Units, ...).
Das macht auch das Debuggen deutlich einfacher.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#5

AW: Windows tötet Delphi-Anwendung noch vor Unit-Finalisierung

  Alt 24. Dez 2015, 00:00
Wobei, ab Vista ist Windows da nicht mehr so gutmütig. Und das ist auch richtig.

Sorg dafür, dass da nichts wichtiges mehr passiert.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.176 Beiträge
 
Delphi 10 Seattle Enterprise
 
#6

AW: Windows tötet Delphi-Anwendung noch vor Unit-Finalisierung

  Alt 24. Dez 2015, 07:48
Vielen Dank für die Antworten bislang.

musst du das währen der WM_ENDSESSION Nachricht machen.
Aber das tue ich doch. In "Halt" beendet sich Delphi sogar mit ExitProcess selbst anstatt darauf zu warten dass Windows es tut. De facto antwortet die Anwendung nie auf WM_ENDSESSION, sondern schießt sich selbst vorher ab. Was ja auch an sich nicht verkehrt ist.

Und wenn du etwas erledigen musst, das länger dauert, musst du Windows das mitteilen. Du kannst dich entsprechend registrieren und wirst dann auch auf dem Herunterfahren-Bildschirm angezeigt in der Liste der Anwendungen, die das Herunterfahren blockieren.
Du meinst ShutdownBlockReasonCreate(..), richtig? Ich versuche es nochmal, das hat aber keinen Unterschied gemacht.
Vielleicht könnte es doch helfen, denn vielleicht gelten die von Uwe angesprochenen fünf Sekunden ja nachträglich wenn die Anwendung plötzlich kein sichtbares Fenster mehr hat:
die Windows wartet, bis es eine Anwendung als unresponsive einfach killt.
Aber ich kann die "Sleep"-Zeit im Beispiel auch auf 15 Sekunden hochdrehen. Das zweite "ZZzz" wird trotzdem immer problemlos auf die Platte gespeichert. Das Problem ist nicht die Zeit, sondern das, was durch "Halt" in irgendeiner der Unit-Finalisierungen passiert...



Wir haben keinerlei wichtigen Code in finalization drin. In finalization passieren nur noch Sachen, auf die wir keinen Einfluss haben (Delphi-Units, 3rd-Party Units, ...).
Das heißt theoretisch müsste man sagen "Unit-Finalisierung und Klassen-Destruktoren: Naja- Können ausgeführt werden, vielleicht aber auch nicht."?
Wir haben leider durchaus Anwendungen welche im Klassen-Destruktor noch beispielsweise Dateien flushen und schließen. Jetzt im Nachhinein zu sehen dass höchstwahrscheinlich nicht ausgeführt wird wenn Windows heruntergefahren wird und die Anwendung noch offen ist schockiert mich ehrlich gesagt etwas ziemlich.

Sorg dafür, dass da nichts wichtiges mehr passiert.
Wie soll das gehen? Ich könnte nach WM_QUERYENDSESSION schon anfangen die Zelte abzubauen, aber helfen tut mir das im Endeffekt doch auch nichts...


Meine Vermutung zur Ursache des vorzeitigen Ablebens bleibt weiterhin dass irgendeine Unit-Finalisierung der VCL/RTL weiterhin in der Nachrichtenschleife der Anwendung wühlt und Windows die Anwendung darauf hin direkt killt.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#7

AW: Windows tötet Delphi-Anwendung noch vor Unit-Finalisierung

  Alt 24. Dez 2015, 10:40
musst du das währen der WM_ENDSESSION Nachricht machen.
Aber das tue ich doch. In "Halt" beendet sich Delphi sogar mit ExitProcess selbst anstatt darauf zu warten dass Windows es tut. De facto antwortet die Anwendung nie auf WM_ENDSESSION, sondern schießt sich selbst vorher ab. Was ja auch an sich nicht verkehrt ist.
Du sagst, dass du deiner Anwendung schon selber ein WM_ENDSESSION geschickt hast.

Wie schickst du denn? Mit SendMessage ?
Dann bleibt also diese sendende Anwendung hängen? (Weil SendMessage blockiert, bis es eine Rückmeldung bekommt)

Oder bekommst du dort doch eine Rückmeldung?

Einfach mal ausprobieren und ich wette, da kommt etwas zurück
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#8

AW: Windows tötet Delphi-Anwendung noch vor Unit-Finalisierung

  Alt 24. Dez 2015, 11:09
Nur mal so al "Spekulatius":

Warum Halt?

Würde das Programm lieber "regulär" beenden, statt Halt(0); mit Application.MainForm.Close; .
Beende meine Programme eigentlich immer damit, dass ich das Hauptformular schließe.

Die Hilfe von Delphi 7 sagt zu Halt:
Zitat von Delphi-Hilfe:
Beschreibung

Die Prozedur Halt löst einen Programmabbruch aus und gibt die Steuerung an das Betriebssystem zurück.
und genau das scheint ja auch zu passieren. Warum soll denn dann noch was ausgeführt werden?

Ansonsten: Wie wäre es mit dem ebenfalls in der Hilfe beschriebenen:
Zitat von Delphi-Hilfe:
Beschreibung

Rufen Sie Terminate auf, um die Anwendung programmgesteuert zu beenden. Durch einen Aufruf der Methode Terminate wird das Anwendungsobjekt nicht einfach gelöscht, die Anwendung kann vielmehr ordnungsgemäß heruntergefahren werden.
Also Application.Terminate; ?

Warum das Programm "brutal" mit Halt beenden, wenn es auch moderat geht?
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.176 Beiträge
 
Delphi 10 Seattle Enterprise
 
#9

AW: Windows tötet Delphi-Anwendung noch vor Unit-Finalisierung

  Alt 24. Dez 2015, 11:15
Halt nehme ich da es
1. Die VCL auch von selbst so macht (siehe weiter unten)
2. Ich keine andere Möglichkeit kenne die Units finalisieren zu lassen


Einfach mal ausprobieren und ich wette, da kommt etwas zurück
Uh, nein, da kommt gar nichts zurück. Die Vcl sagt standardmäßig:

Delphi-Quellcode:
Vcl.Forms.TApplication.WndProc(..)
begin
   [...]
   WM_ENDSESSION:
      begin
         [...]
         if EndSessionMsg.EndSession then begin
            Application.Terminate;
            Halt;
            end;
   [...]
end;
Halt ist, soweit ich weiß, die einzige Möglichkeit, die Unit-Finalisierung aufzurufen.

System.Halt sagt:

Delphi-Quellcode:
procedure _Halt0;
begin
   [...]
   FinalizeUnits;
   [...]
   WinApi.Windows.ExitProcess(ExitCode);
end;
Eine VCL-Anwendung antwortet somit nie auf ein WM_ENDSESSION , sondern schießt sich vorher ab. Klingt komisch, ist aber doch völlig legitim. Ich denke eher das Abräumen der Formulare sorgt dafür dass Windows denkt "So, der ist ja durch. Weg mit dem".

Ich versuche mal, schon alle Formulare in WM_QUERYENDSESSION zu zerstören. Vielleicht bringt das ja was...

Geändert von Der schöne Günther (24. Dez 2015 um 11:19 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#10

AW: Windows tötet Delphi-Anwendung noch vor Unit-Finalisierung

  Alt 24. Dez 2015, 11:15
Warum das Programm "brutal" mit Halt beenden, wenn es auch moderat geht?
Weil Borlacadero das so in procedure TApplication.WndProc(var Message: TMessage); programmiert hat?
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      

 

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 17:56 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