![]() |
AW: In Konsolenanw. auf Firebird-Events reagieren?
Klappt auch mit IBDAC.
Delphi-Quellcode:
Dann noch in PSQL den Event feuern und nicht vergessen zu committen.
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.
Code:
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:
set term !! ;
execute block as begin post_event('Event1'); end !! set term ; !! commit; |
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... |
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:
Application ändert an der ganzen Geschichte übrigens nichts, also hab ich die Unit Forms wieder rausgeschmissen und nutze meine eigene Message-Schleife weiter.
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; |
AW: In Konsolenanw. auf Firebird-Events reagieren?
Zitat:
![]() 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". |
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.
![]() 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 05:24 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