AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Normale Exceptions nicht anzueigen

Offene Frage von "shmia"
Ein Thema von FAlter · begonnen am 3. Sep 2007 · letzter Beitrag vom 7. Sep 2007
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von FAlter
FAlter

Registriert seit: 21. Jul 2004
Ort: Ostfildern
1.096 Beiträge
 
FreePascal / Lazarus
 
#1

Normale Exceptions nicht anzueigen

  Alt 3. Sep 2007, 18:14
Hi,

ich suche nach einer eleganten Methode, an einer bestimmten Stelle (und nur dort) die Anzeige von Exceptions zu unterdrücken.

Theoretisch wäre ja
Delphi-Quellcode:
try
  ..
except
  on EMyException do;
end;
möglich, aber das Thema wurde ja bereits oft diskutiert und vom Schlucken von Exceptions wurde abgeraten - zumal es mir lieb wäre, wenn man in höherer Ebene die Exception noch mit try-except abfangen konnte. Nur, sollte dies nicht passieren, so sollte die Exception nicht zur Anzeige einer Meldung führen. Da dies nicht generell für alle Exceptions dieses Types gelten soll, hilft Application.OnException o. ä. nicht.

Vielleicht so?

Delphi-Quellcode:
type
  ESilentException = class(Exception)
  ...
  public
    constructor Create(OriginalException: Exception);
    property OriginalException: Exception read ...;
    destructor Destroy; override;
  end;

  ...
  on E: EMyException do
    raise ESilentException.Create(E);

  ...
  //auf höherer Ebene wäre Behandlung bei Bedarf noch möglich...
  on E: ESilentException do
  begin
    //Behandlung Stiller Exceptions z. B.
    if E.OriginalException is EMyException then
      HandleMyException;
  end;
Aber wie sieht es dann mit der Freigabe der Original-Exception aus? Denn normaler weise wird sie ja automatisch freigegeben, nachdem sie behandelt (oder angezeigt) wurde. Aber das soll ja hier nicht passieren, da sie in ESilentException noch benötigt wird, bis auch jene abgearbeitet wurde (welche nun z. B. in Application.OnException unterdrückt werden könnte - bei Bedarf). Das Freigeben des Originals sollte also möglichst im destruktor der neuen Exception - und nur dort - geschehen.

Bietet Delphi oder die VCL irgendeine elegante Lösung für diesen Fall, und falls nicht, wie könnte man es tun?

Mfg
FAlter
Felix Alter
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#2

Re: Normale Exceptions nicht anzueigen

  Alt 3. Sep 2007, 18:35
Bei einem Seriendruck können ja auch Exceptions auftreten.
Der Benutzer kann auswählen was er tun möchte.
1.) Fehler ignorieren, auf Nachfrage abbrechen
2.) Fehleretikett drucken
3.) sofort abbrechen
Ausserdem werden alle Exceptions in einem Memo protokolliert.
Delphi-Quellcode:
procedure TSerienDruckForm.HandleException(E: Exception);
begin
   AddError(E.Message); // Memo1.lines.Add(...)

   case RgpErrorAction.ItemIndex of
      0: // Druckauftrag ignorieren
      begin
         if MessageDlg(E.Message + #13#10 + 'Seriendruck abbrechen ?', mtError, [mbYes, mbNo], 0) = mrYes then
            Abort;
      end;
      1: // Fehleretikett
      begin
         DMPrtFehlerEtikett.PrintFehlerEtikett(E);
      end;
      2: // Seriendruck abbrechen, Exception erneut auslösen
      begin
         // "raise E" will nicht, daher neue Exception erzeugen.
         raise Exception.Create(E.Message);
      end;
      else
      begin
         Assert(False);
      end;
   end;
end;
Die Fehlerbehandlung sieht dann so aus:
Delphi-Quellcode:
 try
   EinzelauftragAbarbeiten;
 except
   on E: Exception do
   begin
    // Auftrag als fehlerhaft markieren
    .....

    HandleException(E);
 end;
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von FAlter
FAlter

Registriert seit: 21. Jul 2004
Ort: Ostfildern
1.096 Beiträge
 
FreePascal / Lazarus
 
#3

Re: Normale Exceptions nicht anzueigen

  Alt 3. Sep 2007, 19:25
Hi,

solch eine Lösung ließe sich jedoch nicht auf höherer Ebene abfangen.

Delphi-Quellcode:
try
  ...
  try
    ...
  except
    on E: EMyException do
      HandleException(E);
  end;
  ...
except
  //Hier würde sich diese Exception nicht erneut abfangen lassen
end;
Mfg
FAlter
Felix Alter
  Mit Zitat antworten Zitat
Dezipaitor

Registriert seit: 14. Apr 2003
Ort: Stuttgart
1.701 Beiträge
 
Delphi 7 Professional
 
#4

Re: Normale Exceptions nicht anzueigen

  Alt 3. Sep 2007, 22:57
Um eine erneute Exception eines anderen Typs zu werfen, jedoch die Daten der alten Exception zu übernehmen,
könntest du einfach einen Kopierkonstruktor nehmen:

Delphi-Quellcode:
type
ESilentException = class(Exception)
public
 ..
 constructor Create(oldException : Exception);
 ..
end;
...

constructor ESilentException.Create(oldException : Exception);
begin
 Message := oldException;
 ...und was sonst noch wichtig wäre.
end;


So jetzt dein Code:
  ...
  on E: EMyException do
    raise ESilentException.Create(E);

  ...
  //auf höherer Ebene wäre Behandlung bei Bedarf noch möglich...
  on E: ESilentException do
  begin
    //Behandlung Stiller Exceptions z. B.
    if E.OriginalException is EMyException then
      HandleMyException;
  end;
Und wenn du das stattdessen für eine Basisklasse XYException machst, und alle Exceptions davon ableitest :
EXYException = class(MyBaseExecption)

Dann brauchste den Kopierkonstruktor nicht für alle nötigen Exceptions implementieren.
Christian
Windows, Tokens, Access Control List, Dateisicherheit, Desktop, Vista Elevation?
Goto: JEDI API LIB & Windows Security Code Library (JWSCL)
  Mit Zitat antworten Zitat
Benutzerbild von turboPASCAL
turboPASCAL

Registriert seit: 8. Mai 2005
Ort: Sondershausen
4.274 Beiträge
 
Delphi 6 Personal
 
#5

Re: Normale Exceptions nicht anzueigen

  Alt 4. Sep 2007, 06:28
Mal so nebenbei, silent Exceptions... das ist wie wenn die Frau (oder deren Mann) eine Beule ins Auto fährt und niemandem etwas davon erzählt.

Exceptions sind doch dafür da unm jmd darauf aufmerksam zu machen.
Matti
Meine Software-Projekte - Homepage - Grüße vom Rüsselmops -Mops Mopser
  Mit Zitat antworten Zitat
Gruber_Hans_12345

Registriert seit: 14. Aug 2004
1.438 Beiträge
 
Delphi 2007 Professional
 
#6

Re: Normale Exceptions nicht anzueigen

  Alt 4. Sep 2007, 16:22
warum nicht einfach?


Delphi-Quellcode:
try
except
  on e : exception do begin
    if silent then SilentException(E)
    else raise;
  end;
end;
dann wird doch die exception 1:1 erneut geraist ...
Gruss Hans

2B or not 2B, that is FF
  Mit Zitat antworten Zitat
Benutzerbild von FAlter
FAlter

Registriert seit: 21. Jul 2004
Ort: Ostfildern
1.096 Beiträge
 
FreePascal / Lazarus
 
#7

Re: Normale Exceptions nicht anzueigen

  Alt 5. Sep 2007, 18:25
Hi,

nur die Daten kopieren hätte den Nachteil, dass spezielle Eigenschaften spezieller Exceptions ignoriert würden. Oder war gemeint, einfach die Instanz der Exception zuzuweisen (da du Message := OldException geschieben hast, Message ist ja ein String-Property, das würde so also gar nicht gehen). Beim speichern der Instanz wäre das Problem mit dem Freigeben.

Ein if Silent then ... geht am eigentlichen Problem dabei, denn an übergeordneter Stelle wären solche Exceptions 1. nicht mehr abfangbar und 2. ist dort gar nicht bekannt, ob sie still sein sollten (falls dort das if silent then hinkommen sollte).

Der Vergleich mit dem Auto hat ein kleines Problem. Würdest du bei einem Unfall zum Bescheid sagen einen weiteren Unfall riskieren?

Nehmen wir an, irgendwo auf einer Komponente wird ein Bild gezeichnet, und es tritt eine Exception auf, eine Meldung wird angezeigt. Der User klickt auf OK, die Komponente ist nicht mehr von der MessageBox verdeckt und so muss das Bild neu gezeichnet werden, was wieder fehlschlägt. Natürlich ließe sich für diesen Fall speichern, dass dieses Bild irgendwie defekt ist, aber das wäre ein beispiel, wo man auch solche stillen Exceptions nehmen könnte. Und das würde eventuell trotzdem beim nächsten Bild (falls diese wechseln, da ein Fehler davon noch nicht bekannt ist) möglicherweise wieder zu einer Exception führen. Beispielsweise bei einer defekten Diskette oder CD.

Oder es werden Zeitabhängig bestimmte Dinge getan (einfachstes Beispiel wäre ein Timer) und dort treten ab und zu Exceptions auf. Das wäre richtig nervend für den User, da er dann eventuell neue Exceptions bekommt, bevor er aus OK geklickt hat. Wie gesagt, einfach die Exceptions durch leeren except-Block schlucken will ich nicht, aber ausblenden will ich sie. Das bedeutet aber nicht, dass diese Exception, falls sie ganz woanders auftritt, auch nicht angezeigt werden soll.

Stattdessen will ich nur in meinem Code aus den Exceptions (aus fremden Code oder aus der VCL) in stille Exceptions umwandeln, sie aber noch abfangbar lassen.

Also, Eigenschaften kopieren ist eine Lösung, jedoch nicht allgemein genug, da eine Exception-Klasse auch neue Eigenschaften einführen kann, und ich will nicht für jede eventuelle Exception, die auftreten könnte, eine neue stille Exception einführen, wenn es eine bessere Möglichkeit gibt.

Eventuell weiß ja jemand, wie man das freigeben einer Exception-Klasse verhindern kann, dann köntne mein oben geschilderter Ansatz nämlich funktionieren. Wenn nicht, muss ich es, so wie es jetzt aussieht, wohl oder übel wie von TP vorgeschlagen, per Eigenschaften kopieren machen.

Mfg
FAlter
Felix Alter
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#8

Re: Normale Exceptions nicht anzueigen

  Alt 5. Sep 2007, 19:46
Zu einem bestimmten Zeitpunkt kann es nur eine aktive Exception geben. (siehe function ExceptObject)
Diese Exception wird automatisch von der VCL (bzw. Compiler-Magic) freigegeben.

Man könnte sich nun eine Objekt-Liste (TObjectList) vorstellen, in der man Kopien der Exception-Objekte sammelt, bis man Zeit hat, alle gemeinsam dem Benutzer zu präsentieren.
Das Problem ist aber, dass sich Exceptions nicht so einfach kopieren lassen. (sie haben keinen virtuellen Konstruktor und auch keine Assign-Methode)

Eine andere Möglichkeit wäre, der VCL vorzutäuschen, dass das Exception-Object schon freigegeben wurde.
Delphi-Quellcode:
var
  FExceptionList : TExceptionList; // siehe Anhang, da wird der Trick gelüftet
...
procedure TForm1.Timer1Timer(Sender: TObject);
begin
   try
     // Exception provozieren
     raise EBitsError.Create('Fehler im Timer '+TimeToStr(Time));
   except
     FExceptionList.AddException;
   end;
end;
Angehängte Dateien
Dateityp: pas exceptionlist_104.pas (1,1 KB, 10x aufgerufen)
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von FAlter
FAlter

Registriert seit: 21. Jul 2004
Ort: Ostfildern
1.096 Beiträge
 
FreePascal / Lazarus
 
#9

Re: Normale Exceptions nicht anzueigen

  Alt 5. Sep 2007, 20:06
Hi,

so lange sich

Delphi-Quellcode:
type
  PRaiseFrame = ^TRaiseFrame; // aus Unit System
  TRaiseFrame = packed record
    NextRaise: PRaiseFrame;
    ExceptAddr: Pointer;
    ExceptObject: TObject;
    ExceptionRecord: PExceptionRecord;
  end;
nicht ändert, hast du mir geholfen. Danke, mit dem Code aus der Unit kann ich was anfangen.

Sieht das bei allen Delphi-Versionen so aus? Und wie stehen die Chancen, dass sich in Zukunft etwas ändert? Es steht ja immernin nicht im interface-Abschnitt der System-Unit.

Mfg
FAlter
Felix Alter
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#10

Re: Normale Exceptions nicht anzueigen

  Alt 6. Sep 2007, 12:27
Zitat von FAlter:
Sieht das bei allen Delphi-Versionen so aus? Und wie stehen die Chancen, dass sich in Zukunft etwas ändert? Es steht ja immernin nicht im interface-Abschnitt der System-Unit.
Die Struktur stammt aus Delphi 5.
Ich denke mal, dass Borland innerhalb von Win32-Anwendungen keinen Grund hat, daran etwas zu ändern.
Bei .NET könnte das aber schon anderst aussehen.
Mitleser anderer Delphi Prof& Enterprise Versionen sind aufgerufen, die Struktur zu vergleichen.
Andreas
  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 10:27 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