Autor Beitrag
Mossi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 99
Erhaltene Danke: 2

Win XP, Linux
D7 Enterprise, K3 Prof
BeitragVerfasst: 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:
ausblenden 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
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 1655
Erhaltene Danke: 13

WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
BeitragVerfasst: 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.


ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
initialization 
  if not LoadConnection then Halt;

finalization

end.

_________________
Popov
ErnestoChe
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 528

Win 2000 pro, CRUX 2.0
Delphi 6 Pers, Open K3
BeitragVerfasst: 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:

ausblenden 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



BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 99
Erhaltene Danke: 2

Win XP, Linux
D7 Enterprise, K3 Prof
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 1655
Erhaltene Danke: 13

WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 99
Erhaltene Danke: 2

Win XP, Linux
D7 Enterprise, K3 Prof
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 528

Win 2000 pro, CRUX 2.0
Delphi 6 Pers, Open K3
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 99
Erhaltene Danke: 2

Win XP, Linux
D7 Enterprise, K3 Prof
BeitragVerfasst: 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

ausblenden 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
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 1655
Erhaltene Danke: 13

WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 99
Erhaltene Danke: 2

Win XP, Linux
D7 Enterprise, K3 Prof
BeitragVerfasst: Fr 05.03.04 22:01 
Ok ich bin ein Vollidiot :oops:

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
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 1655
Erhaltene Danke: 13

WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 528

Win 2000 pro, CRUX 2.0
Delphi 6 Pers, Open K3
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 1655
Erhaltene Danke: 13

WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: 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:
ausblenden Delphi-Quelltext
1:
PostMessage(Handle, WM_CLOSE, 00);					

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!