Autor |
Beitrag |
Mossi
      
Beiträge: 99
Erhaltene Danke: 2
Win XP, Linux
D7 Enterprise, K3 Prof
|
Verfasst: Fr 05.03.04 19:34
Ich versuche gerade, dass ich bei einem kontrollierten Fehler im FormCreate das Programm gleich wieder beende. Allerdings stoße ich dabei auf eine EAccessViolation. Gibt es da eine Möglichkeit, wie ich das umgehen kann?
Hier der entsprechende Auszug aus dem Quellcode:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure TfrmMain.FormCreate(Sender: TObject); begin FPluginNames := TStringList.Create;
if LoadConnection then LoadSheets else self.Destroy; end; |
Beim Destroy tritt dann der Fehler auf.
Es geht dabei um folgendes: Die Funktion LoadConnection lädt eine DLL, die eine Datenbankverbindung aufbaut. Wenn das schief geht (falsches Passwort, oder Datenbank nicht erreichbar...) liefert die Funktion "False" zurück. Wenn das der Fall ist, soll dann das Programm gleich wieder geschlossen werden, weil es dann eh keinen Sinn macht weiter zu machen (das Programm basiert zu hundert Prozent auf einer Datenbank)
Ich befürchte jetzt mal, dass es deswegen nicht geht, weil im FormCreate die Form noch nicht vollständig erzeugt ist und daher der Destroy schief geht. Vielleicht gibt es so etwas wie ein AfterCreate-Event, in dem ich dann das alles machen kann.
|
|
Popov
      
Beiträge: 1655
Erhaltene Danke: 13
WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
|
Verfasst: Fr 05.03.04 20:52
Ich kann dir zwei Tipps anbieten:
1. Ein Timer. Er ist False und wird als letztes in Create auf True gesetzt und beendet das Programm nach z.B. 250ms (kurze Verzögerung muß schon sein). Auf diese Weise bist du bereits raus aus Create.
2. Du machst die Einbindung nicht in Crate, sondern im Initialization Teil. Der wird nicht automatisch erstellt wie z.B. der Implementation Teil. Der Initialization Teil wird noch vor Create ausgeführt. Solange du nicht auf eine Komponente zugreifts ist es egal ob du es im Initialization Teil machst.
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| initialization if not LoadConnection then Halt;
finalization
end. |
_________________ Popov
|
|
ErnestoChe
      
Beiträge: 528
Win 2000 pro, CRUX 2.0
Delphi 6 Pers, Open K3
|
Verfasst: Fr 05.03.04 21:07
Hallo,
@Mossi
Destroy ist definitiv die falsche Methode um ein Programmn zu beenden. Destroy ist der Destruktor von TForm und sollte ohnehin nicht direkt aufgerufen werden, sondern die Methode Free - und um ein Programm zu beenden schon mal gar nicht. Was du brauchst ist ein:
Delphi-Quelltext 1:
| Application.Terminate; |
@Popov
Halt ist auch nicht die optimale Prozedur um ein Programm zu beenden. Siehe dazu Delphi-Hilfe.
MFG
- Ernesto -
|
|
Brainiac
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Fr 05.03.04 21:25
Da hier gerade ein ähnliches Problem vorliegt vielleicht mal etwas, das ich mich schon länger gefragt habe:
Kann man eigentlich die Konstruktion einer Instanz irgendwie während des Konstruktors abbrechen, ohne das ganze Programm anzuhalten?
z.B. wenn festgestellt wird, das eine wichtige Voraussetzung für die Existenz der Komponente nicht besteht, oder so.
|
|
Mossi 
      
Beiträge: 99
Erhaltene Danke: 2
Win XP, Linux
D7 Enterprise, K3 Prof
|
Verfasst: Fr 05.03.04 21:28
Hmmm...
Ok das hört sich schon einmal ganz gut an. Allerdings funktioniert es nicht
Das Problem ist, dass "LoadConnections" eine Function der Form ist
-> Undeclared identifier: 'LoadConnection'
Ich kann das auch schlecht anders machen, da ich ja diese Connection in genau dieser Form brauche.
Weder "Application.Terminate" noch "Halt" noch "Free" funktionieren im CreateForm
|
|
Popov
      
Beiträge: 1655
Erhaltene Danke: 13
WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
|
Verfasst: Fr 05.03.04 21:29
ErnestoChe hat folgendes geschrieben: | Halt ist auch nicht die optimale Prozedur um ein Programm zu beenden. Siehe dazu Delphi-Hilfe. |
Bitte keine Pauschalaussagen. Es gibt einen Unterschied ob du Halt einsetzt nachdem die Formulare und die ganzen Objekte erstellt wurden oder vorher. Die Aussage in der Hilfe bezieht sich auf die Regel. Und in der Regel beendet man Programme irgendwann und nicht bereits am Anfang.
Nein, der Tipp mit Halt ist schon Ok, zumindest an dieser Stelle (d.h. im Initialization Teil).
_________________ Popov
|
|
Mossi 
      
Beiträge: 99
Erhaltene Danke: 2
Win XP, Linux
D7 Enterprise, K3 Prof
|
Verfasst: Fr 05.03.04 21:38
Ok. aber wie kann ich meine Function im Initialization-Teil bekannt machen?
Aus irgendeinen Grund kennt er sie an dieser Stelle nicht. Oder muss ich dann die Function aus der Klasse der Form herausnehmen und außerhalb deklarieren?
|
|
ErnestoChe
      
Beiträge: 528
Win 2000 pro, CRUX 2.0
Delphi 6 Pers, Open K3
|
Verfasst: Fr 05.03.04 21:48
Hallo,
@Mossi
Zeig mal fie Funktion LoadConnections. Wenn die irgendwas mit Komponenten auf der Form macht kannst du den Tipp im initialization ohnehin vergessen und wahrscheinlich ist OnCreate zu früh.
@Popov
Application.Terminate fährt die Anwendung ordnungsgemäß runter. Und wenn ich die Möglichkeit habe etwas ordnungsgemäß zu tun ziehe ich das der abrupten Methode vor.
MFG
- Ernesto -
|
|
Mossi 
      
Beiträge: 99
Erhaltene Danke: 2
Win XP, Linux
D7 Enterprise, K3 Prof
|
Verfasst: Fr 05.03.04 21:56
Also ich bin jetzt schon einmal drauf gekommen, dass ich die Function aus der Klasse der Form herausnehmen muss. Ist ja auch irgendwie logisch, da ja die Klasse noch nicht erstellt ist. Aber funktionieren tut's dennoch noch nicht.
Hier mal der Code von LoadConnection. Vielleicht sieht hier jemand einen Logikfehler
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
| function TfrmMain.LoadConnection: Boolean; var DllHandle: THandle; GetConnectionProc: TGetConnection; begin try DllHandle := LoadLibrary('Connection.dll'); if DllHandle = 0 then begin ShowMessage('ConnectionLib not found'); FreeLibrary(DllHandle); Result := False; end else begin @GetConnectionProc := GetProcAddress(DllHandle, 'GetConnection'); FConnection := GetConnectionProc(nil);
Result := FConnection.Connected; end; except on E:Exception do begin ShowMessage(E.ClassName + ':' + E.Message); Result := False; end; end; end; |
Ich hoffe mal nicht, dass ich hier irgendwo einen Fehler drin habe...
|
|
Popov
      
Beiträge: 1655
Erhaltene Danke: 13
WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
|
Verfasst: Fr 05.03.04 21:58
@Mossi
So ist es. Allerdings kenne ich die Funktion nicht und weiß nicht ob es geht. Es ist aber so, daß der Initialization Teil zuerst in der Unit ausgeführt wird. Allerdings mußten alle Prozeduren und Funktionen bekannt sein, da der Initialization Teil in der Regel am Ende der Unit zu finden ist. Um aber die die Form Prozeduren auszuführen mußt du den Form Namen davorsetzen, z.B. Form1.Button1Click(nil). Allerdings darf man nicht vergessen, daß die Formulare noch nicht erstellt wurden. Wenn in der Prozedur z.B. ein Edit1.Text := '123' steht, dann kommt ein Fehler, da Edit1 noch nicht existiert.
_________________ Popov
|
|
Mossi 
      
Beiträge: 99
Erhaltene Danke: 2
Win XP, Linux
D7 Enterprise, K3 Prof
|
Verfasst: Fr 05.03.04 22:01
Ok ich bin ein Vollidiot
Ich hab im Exception-Teil meiner DLL vergessen, dass ich das Connected-Flag zurücksetze...
Da ich gerade immer einen Fehler provoziert habe (falsches Passwort) ist natürlich der Connect selbst schief gegangen aber das Object galt als "Connected"
Tut mir Leid für die Unruhe, aber manchmal steht man einfach auf der Leitung...
Trotzdem vielen Dank für die Hilfe
|
|
Popov
      
Beiträge: 1655
Erhaltene Danke: 13
WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
|
Verfasst: Fr 05.03.04 22:09
ErnestoChe hat folgendes geschrieben: | @Popov
Application.Terminate fährt die Anwendung ordnungsgemäß runter. Und wenn ich die Möglichkeit habe etwas ordnungsgemäß zu tun ziehe ich das der abrupten Methode vor. |
Das Problem bei Application.Terminate ist, daß Terminate nicht sofort das Programm beendet, sondern eine Nachricht an das System schickt. Irgendwann wird das Programm beendet, aber erst irgendwann. Wer also nicht will, daß sein Programm weiter läuft und eventuell noch schaden anrichtet, der sollte eventuell sein Programm in eine Endlosschleife führen.
_________________ Popov
|
|
ErnestoChe
      
Beiträge: 528
Win 2000 pro, CRUX 2.0
Delphi 6 Pers, Open K3
|
Verfasst: Fr 05.03.04 22:42
Hallo,
wieso sollte die Anwendung bei einem Aufruf von Application.Terminate weiter laufen und schaden anrichten? Application.Terminate ist eine Prozedur und wie wir wissen wird ein Programm bei einem Prozedur-Aufruf erst dann fortgesetzt wenn diese wieder zurückkehrt. Nach einem Aufruf von Application.Terminate werden noch alle Formulare freigegeben, das OnDestroy-Ereignis sowie der finalization-Abschnitt ausgeführt und dann ist die Anwendung beendet.
Höchstens, wenn zu der Applikation noch Threads laufen. Aber die kann man ja vor dem Application.Terminate Aufruf auch noch beenden. Halt sollte in einer WindowsGUI-Anwendung einfach nicht verwendet werden.
MFG
- Ernesto -
// Edit: ich meinte das OnDestroy-Ereignis, nicht das OnClose, ich habs jetzt geändert
Zuletzt bearbeitet von ErnestoChe am Sa 06.03.04 09:46, insgesamt 1-mal bearbeitet
|
|
Popov
      
Beiträge: 1655
Erhaltene Danke: 13
WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
|
Verfasst: Fr 05.03.04 23:16
Text aus der Hilfedatei:
Zitat: | Terminate ruft die Funktion PostQuitMessage der Windows-API auf, um die Anwendung kontrolliert zu beenden. Die Methode Terminate wirkt somit nicht direkt. |
Terminate beendet also nicht direkt das Programm. Meine schlechten Erfahrungen sind die, daß, nachdem ich mit Terminate das Programm beendet habe, es erstmal weiterging. Es hatte aber schon seinen Grund wieso ich das Programm abgebrochen habe. Es folgten jede Menge Fehlermeldungen, da daß Programm weiterlief und auf Werte zugrif die nicht da waren, da diese eigentlich der Grund für den Abbruch waren.
Es sieht nun mal nicht professionel aus wenn solche Meldungen kommen.
_________________ Popov
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Sa 06.03.04 19:07
Was die Möglichkeiten der Programmbeendung betrifft gibt es auch einen netten FAQ-Eintrag: www.delphi-forum.de/viewtopic.php?t=1562
BTW: es gibt Situationen, in denen ein simpler Aufruf von Close nicht immer funktioniert, in diesen Situationen behelfe ich mir meistens mit einem:
Delphi-Quelltext 1:
| PostMessage(Handle, WM_CLOSE, 0, 0); |
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|