Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi In Konsolenanw. auf Firebird-Events reagieren? (https://www.delphipraxis.net/171974-konsolenanw-auf-firebird-events-reagieren.html)

tsteinmaurer 5. Dez 2012 19:46

AW: In Konsolenanw. auf Firebird-Events reagieren?
 
Klappt auch mit IBDAC.

Delphi-Quellcode:
program IBDACEventConsoleTest;

{$APPTYPE CONSOLE}

uses
  SysUtils, IBC, IBCAlerter, Forms, Types, Windows;

type
  TMyEventHandler = class
  public
    procedure DoEventAlert(Sender: TObject; AEventName: string; AEventCount: Longint);
  end;

var
  conn: TIBCConnection;
  alerter: TIBCAlerter;
  isShutdown: Boolean;
  eventHandler: TMyEventHandler;

function ConsoleEventProc(CtrlType : DWord) : Bool; stdcall; far;
begin
  case CtrlType of
    CTRL_C_EVENT,
    CTRL_BREAK_EVENT,
    CTRL_CLOSE_EVENT,
    CTRL_LOGOFF_EVENT,
    CTRL_SHUTDOWN_EVENT: isShutdown := True;
  end;
  Result := True;
end;

{ TMyEventHandler }

procedure TMyEventHandler.DoEventAlert(Sender: TObject; AEventName: string; AEventCount: Integer);
begin
  Writeln(Format('Event: %s received. Count: %d', [AEventName, AEventCount]));
end;

begin
  SetConsoleCtrlHandler(@ConsoleEventProc, True);
  try
    eventHandler := TMyEventHandler.Create;
    try
      conn := TIBCConnection.Create(nil);
      try
        conn.LoginPrompt := False;
        conn.Database := 'localhost/3051:tourism.fdb';
        conn.Username := 'tourism';
        conn.Password := 'tourism';
        conn.Connect;
        alerter := TIBCAlerter.Create(nil);
        try
          alerter.OnEvent := eventHandler.DoEventAlert;
          alerter.Connection := conn;
          alerter.Events.Add('Event1');
          alerter.Active := True;
          isShutdown := False;
          while not isShutdown do
          begin
            Application.HandleMessage;
          end;
        finally
          alerter.Active := False;
          alerter.Free;
        end;
      finally
        conn.Disconnect;
        conn.Free;
      end;
    finally
      eventHandler.Free;
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
Dann noch in PSQL den Event feuern und nicht vergessen zu committen.

Code:
set term !! ;
execute block
as
begin
  post_event('Event1');
end
!!
set term ; !!

commit;
Ich bekomme in der Konsole dann den entsprechenden Output aus meinem Event-Handler. Ob das jetzt hingepfuscht oder sauber ist, können uns die echten Delphi-Geeks hier sagen. :thumb:

RSE 6. Dez 2012 09:09

AW: In Konsolenanw. auf Firebird-Events reagieren?
 
Ich habe gar keine Unit Forms benutzt, zumindest steht es nicht in MEINER Uses-Liste. Habe ich trotzdem ein Application-Objekt?

Ich habe dein ConsoleEventProc übernommen, diese Möglichkeit war mir noch unbekannt. So kann ich jetzt wenigstens auch darauf reagieren, dass einfach die Konsole geschlossen wird. Allerdings verstehe ich den Ablauf noch nicht ganz. ConsoleEventProc sieht bei mir genauso aus wie bei dir. Wenn isShutdown True ist, beende ich meine Aufgaben und verlasse das Programm. Wenn ich allerdings durchdebugge, dann bricht die Ausführung kurz nach (nicht bei!) Beendigung von ConsoleEventProc ab. Den Grund dafür kann ich mir nicht erklären. Die Finallys im Haupt-Begin-End-Block werden (zumindest beim Debuggen) nicht durchlaufen. Ich rufe auch nirgends Halt auf.

Ich will quasi das Beenden der Konsole (Beenden meines Prozesses von außen) unterbinden, um meinen Prozess selbst sauber beenden zu können. Ich muss dabei ggf. auch auf die Beendung des externen Prozesses warten (Ausführung des vom Firebird-Event durch mein Programm getriggerte Batch-Skript). Sind das Schwierigkeiten, die ich mit der Verwendung von Forms und TApplication verhindern könnte? Um das zu testen müsst ich das halbe Prog umschreiben...

RSE 7. Dez 2012 10:36

AW: In Konsolenanw. auf Firebird-Events reagieren?
 
Lösung: Die Prozedur ConsoleEventProc, die mit SetConsoleCtrlHandler registriert wird, läuft asynchron zum Programm in einem anderen Thread. Wenn diese Prozedur beendet wird, wird das Programm "von außen" beendet, sobald offenbar ein weiterer Thread wieder rechenzeit bekommt. Jedenfalls werden nach Beendigung der Prozedur ConsoleEventProc noch ein paar wenige Befehle ausgeführt, bevor das Programm unkontrolliert abbricht. Abhilfe: ConsoleEventProc nie beenden. Damit hat man zumindest bis zum Timeout Zeit, das Programm ordentlich zu beenden.
Delphi-Quellcode:
function ConsoleEventProc(CtrlType: DWord): Bool; stdcall; far;
begin
  // Diese Prozedur läuft asynchron zum Programm in einem eigenen Thread
  case CtrlType of
    CTRL_C_EVENT,
    CTRL_BREAK_EVENT,
    CTRL_LOGOFF_EVENT,
    CTRL_SHUTDOWN_EVENT,
    CTRL_CLOSE_EVENT:
      begin
        // Globale Variable setzen, die regelmäßig abgefragt werden muss
        Terminated := True;
        WriteLn('Shutdown Request received');
        // unendlich warten, um das Programm ordentlich beenden zu können
        // Die Unendlichkeit ist durch einen Windows-Timeout begrenzt
        Sleep(INFINITE);
        // Schließt die Konsole und bricht damit das Programm "von außen" ab
        Result := True;
      end;
    else
      Result := False; // Standard-Handler aufrufen
  end;
end;
Application ändert an der ganzen Geschichte übrigens nichts, also hab ich die Unit Forms wieder rausgeschmissen und nutze meine eigene Message-Schleife weiter.

mjustin 7. Dez 2012 11:02

AW: In Konsolenanw. auf Firebird-Events reagieren?
 
Zitat:

Zitat von RSE (Beitrag 1194636)
Abhilfe: ConsoleEventProc nie beenden. Damit hat man zumindest bis zum Timeout Zeit, das Programm ordentlich zu beenden.

Einige Informationen dazu habe ich hier auf Stackoverflow gefunden:

http://stackoverflow.com/questions/3...-routine-issue

Selbst wenn man eine Endlosschleife einbaut, hat man ab Windows 7 nur zehn Sekunden Zeit (ab dem Eintreten des Ctrl Close Events) für den Prgrammabschluss, dann wird das Programm "abgeschossen".

RSE 7. Dez 2012 13:36

AW: In Konsolenanw. auf Firebird-Events reagieren?
 
Man hat 5 Sekunden für CTRL_CLOSE_EVENT und 20 für CTRL_LOGOFF_EVENT und CTRL_SHUTDOWN_EVENT.

http://www.codeproject.com/Articles/...Event-Handling

Auf diesen Timeout habe ich auch im Kommentar in meinem Quelltext hingewiesen. Beziffert habe ich ihn nicht, da ich weder verlässliche Quellen (Microsoft-Dokument) noch Hinweise auf Unterschiede in verschiedenen Windows-Versionen gefunden habe.


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:01 Uhr.
Seite 2 von 2     12   

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