Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Globale Exceptions abfangen? (https://www.delphipraxis.net/142992-globale-exceptions-abfangen.html)

DelphiPeter 7. Nov 2009 13:26


Globale Exceptions abfangen?
 
Hi Leute, ich habe in eine Prozedur, die globale Exceptions abfangen soll, in einer DLL ausgelagert. Schön mit Formular, Screenshot machen und Bugreport versenden, wie man das eben so kennt.

Nun wollte ich das so, in meiner Demo Anwendung anwenden, was aber nicht funktioniert:

Delphi-Quellcode:
...
  procedure AppException(Sender: TObject; E: Exception); stdcall; external 'toexc.dll';
...
  Application.OnException := AppException;
...
Die DLL Prozedur sieht so aus..

Delphi-Quellcode:
...
procedure AppException(Sender: TObject; E: Exception); stdcall;
begin
  {...}
end;

exports AppExecption;
...
Der Compiler sagt mir beim erzeugen der DEMO Anwendung:

Zitat:

[DCC Fehler] Unit1.pas(40): E2009 Inkompatible Typen: 'Unterschiede in der Aufrufkonvention'
Was habe ich denn nun nicht bedacht? :-)

Apollonius 7. Nov 2009 13:33

Re: Globale Exceptions abfangen?
 
Wie kommst du auf die Idee, dass das stdcall sein sollte? Außerdem kannst du eine normale Routine nicht verwenden, du brauchst eine Methode.

mirage228 7. Nov 2009 13:36

Re: Globale Exceptions abfangen?
 
Zitat:

Zitat von Apollonius
Außerdem kannst du eine normale Routine nicht verwenden, du brauchst eine Methode.

Naja doch, wenn er in der Anwendung den Exception-Handler normal definiert und dort drin die DLL-Methode aufruft (die Parameter sozusagen weiterreicht) ;)

@DelphiPeter: Du musst höllisch aufpassen, da die DLL ihre eigene VCL mit reinverlinkt, und das furchtbar krachen kann (insb. wenn die DLL mit einer anderen Delphi Version erstellt wurde) -- du könntest Dir überlegen BPLs zu verwenden :)

DelphiPeter 7. Nov 2009 13:38

Re: Globale Exceptions abfangen?
 
öhm, ich habe Prozeduren bis dato immer als stdcall aus einer DLL exportiert ?

Zitat:

Du musst höllisch aufpassen, da die DLL ihre eigene VCL mit reinverlinkt, und das furchtbar krachen kann (insb. wenn die DLL mit einer Delphi Version erstellt wurde) -- du könntest Dir überlegen BPLs zu verwenden
So, BPLs klingen da irgendwie besser. Wie gehe ich das am besten an?

mirage228 7. Nov 2009 13:42

Re: Globale Exceptions abfangen?
 
Zitat:

Zitat von DelphiPeter
öhm, ich habe Prozeduren bis dato immer als stdcall aus einer DLL exportiert ?

Muss aber auf beiden Seiten konsistent sein ;) -- wenn Du in Delphi nichts dazuschreibst, hast Du automatisch "register" als Aufrufkonvention und mit stdcall zusammen passt des nicht ;)

Zitat:

Zitat:

Du musst höllisch aufpassen, da die DLL ihre eigene VCL mit reinverlinkt, und das furchtbar krachen kann (insb. wenn die DLL mit einer Delphi Version erstellt wurde) -- du könntest Dir überlegen BPLs zu verwenden
So, BPLs klingen da irgendwie besser. Wie gehe ich das am besten an?
Die einfache Variante ist deine Anwendung mit Laufzeitpackages zu compilieren (siehe Projektoptionen).

Deinen zusätzlichen Code nimmst Du in eines Projekt "Package" und compilierst dieses Package. Den Namen des letzteren bindest Du dann in die Liste der Laufzeitpackages in den Optionen der Hauptanwendung ein.

Beachte: Du musst in dieser Variante alle VCL-BPLs auch mit dazuliefern (neben Deiner eigenen), wenn Du Deine Anwendung weitergibst.

Das ganze noch weitergehend zu erklären, würde denke ich den Rahmen dieses Posts sprechen. Such am besten nach Tutorials, wo die Möglichkeiten genauer erklärt und beschrieben werden.

himitsu 7. Nov 2009 23:07

Re: Globale Exceptions abfangen?
 
Da wie bei vielen/allen Klassen die Typen/Klassen nhand iher "Zeiger" unterschieden werden, ist so eine korrekte Exceptions Auswertung garnicht richtig möglich.

Da eine Exception in der VCL der EXE in der DLL rein abstammungstechnisch nicht von der Exceptions-Basisklasse der DLL abstammen.

Sir Rufo 8. Nov 2009 11:47

Re: Globale Exceptions abfangen?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Da ich die Idee gar nicht mal so abwegig finde, habe ich das mal rudimentär so umgesetzt, wie ich mir das vorstelle :mrgreen:

- Die AppExceptions werden nur umgebogen, wenn die DLL auch vorhanden ist
- Das Umbiegen erfolgt automatisch durch das Einbinden einer Unit
- In dieser Unit wird die Exception in die relevanten Einzelteile zerlegt und der DLL zugeführt

Hier die Unit zum Einbinden:
Delphi-Quellcode:
unit uAppExceptionHandlerClass;

// Dieses ist die Verbindung zwischen dem Delphi-Programm und der DLL

interface

uses
  Windows, SysUtils;

type
  TAppException = procedure( ParentForm, Sender : Pointer; lExeName, lMessage,
    lStackTrace : PChar; HelpContext : integer );

type
  TAppExceptionHandlerClass = class
  private
    FDLLHandle : cardinal;
    procedure SetDLLHandle( const Value : cardinal );
    function GetFarProc( const FarProcName : string; var FarProc : TFarProc )
      : boolean;

  public
    property DLLHandle : cardinal read FDLLHandle write SetDLLHandle;
    procedure AppExceptionHandler( Sender : TObject; E : Exception );
    function LoadDLL : boolean;
    function UnloadDLL : boolean;
  end;

var
  FAppExceptionHandler : TAppExceptionHandlerClass;

implementation

uses
  Dialogs, Forms;

const
  AppExceptionHandlerDLLName = 'insaexhd.dll';

procedure BindDLL;
  var
    proc : TFarProc;
  begin
    with FAppExceptionHandler do
      if LoadDLL then
        if GetFarProc( 'AppException', proc ) then
          Application.OnException := AppExceptionHandler;
  end;

procedure UnbindDLL;
  begin
    with FAppExceptionHandler do
      if not UnloadDLL then
        ShowMessage( 'DLL konnte nicht entladen werden!' );
  end;

{ TAppExceptionHandlerClass }

procedure TAppExceptionHandlerClass.AppExceptionHandler
  ( Sender : TObject; E : Exception );
  var
    proc : TFarProc;
  begin
    if GetFarProc( 'AppException', proc ) then
      TAppException( proc )( Application.MainForm, Sender, PChar
          ( Application.ExeName ), PChar( E.Message ), PChar( E.StackTrace ),
        E.HelpContext );
  end;

function TAppExceptionHandlerClass.GetFarProc( const FarProcName : string;
  var FarProc : TFarProc ) : boolean;
  begin
    if LoadDLL then
      FarProc := GetProcAddress( DLLHandle, PChar( FarProcName ) )
    else
      FarProc := nil;
    RESULT := Assigned( FarProc );
  end;

function TAppExceptionHandlerClass.LoadDLL : boolean;
  begin
    if ( DLLHandle = 0 ) then
      DLLHandle := LoadLibrary( PChar( AppExceptionHandlerDLLName ) );
    RESULT := ( DLLHandle <> 0 );
  end;

procedure TAppExceptionHandlerClass.SetDLLHandle( const Value : cardinal );
  begin
    FDLLHandle := Value;
  end;

function TAppExceptionHandlerClass.UnloadDLL : boolean;
  begin
    if ( DLLHandle <> 0 ) then
      if FreeLibrary( DLLHandle ) then
        DLLHandle := 0;
    RESULT := ( DLLHandle = 0 );
  end;

initialization

FAppExceptionHandler := TAppExceptionHandlerClass.Create;
BindDLL;

finalization

UnbindDLL;
FreeAndNil( FAppExceptionHandler );

end.
Die DLL im Anhang ist mit D2010 compiliert, somit sind die Parameter vom Typ PWideChar!
Dieses sollte/müsste in dem Projekt noch berücksichtigt werden, damit eine DLL auch
universell einsetzbar ist.

cu

Oliver


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:18 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