![]() |
Normale Exceptions nicht anzueigen
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:
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.
try
.. except on EMyException do; end; Vielleicht so?
Delphi-Quellcode:
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.
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; Bietet Delphi oder die VCL irgendeine elegante Lösung für diesen Fall, und falls nicht, wie könnte man es tun? Mfg FAlter |
Re: Normale Exceptions nicht anzueigen
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:
Die Fehlerbehandlung sieht dann so aus:
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;
Delphi-Quellcode:
try
EinzelauftragAbarbeiten; except on E: Exception do begin // Auftrag als fehlerhaft markieren ..... HandleException(E); end; |
Re: Normale Exceptions nicht anzueigen
Hi,
solch eine Lösung ließe sich jedoch nicht auf höherer Ebene abfangen.
Delphi-Quellcode:
Mfg
try
... try ... except on E: EMyException do HandleException(E); end; ... except //Hier würde sich diese Exception nicht erneut abfangen lassen end; FAlter |
Re: Normale Exceptions nicht anzueigen
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:
Und wenn du das stattdessen für eine Basisklasse XYException machst, und alle Exceptions davon ableitest :
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; EXYException = class(MyBaseExecption) Dann brauchste den Kopierkonstruktor nicht für alle nötigen Exceptions implementieren. |
Re: Normale Exceptions nicht anzueigen
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. |
Re: Normale Exceptions nicht anzueigen
warum nicht einfach?
Delphi-Quellcode:
dann wird doch die exception 1:1 erneut geraist ...
try
except on e : exception do begin if silent then SilentException(E) else raise; end; end; |
Re: Normale Exceptions nicht anzueigen
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 |
Re: Normale Exceptions nicht anzueigen
Liste der Anhänge anzeigen (Anzahl: 1)
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; |
Re: Normale Exceptions nicht anzueigen
Hi,
so lange sich
Delphi-Quellcode:
nicht ändert, hast du mir geholfen. Danke, mit dem Code aus der Unit kann ich was anfangen.
type
PRaiseFrame = ^TRaiseFrame; // aus Unit System TRaiseFrame = packed record NextRaise: PRaiseFrame; ExceptAddr: Pointer; ExceptObject: TObject; ExceptionRecord: PExceptionRecord; end; 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 |
Re: Normale Exceptions nicht anzueigen
Zitat:
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. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:59 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz