Close Event - Konsolenanwendung



  • Hi,
    ich habe ein kleines Konsolenprogramm geschrieben, das, wenn man es versucht zu schließen, vorher noch eine Message Box ausgeben soll.
    Dazu müsste ich ja das Close-Event, das beim Schließen ausgelöst wird, irgendwie abfangen.
    Durch die Suchfunktion habe ich auch schon einige Codebeispiele gefunden - allerdings nur für Windows-Forms-Anwendungen, deshalb funktionieren sie bei mir leider nicht.

    Kann man das Close-Event auch bei Konsolenanwendungen abfangen? Wenn ja wie?

    schonmal danke für die Hilfe,
    Andreas.


  • Mod



  • irgendwie verstehe ich noch nicht richtig wie es damit funktionieren soll;
    wo im code muss ich denn das hinschreiben was es tun soll wenn es geschlossen wird?

    ein Ausschnitt meines jetztigen Codes:

    #include<iostream>
    #include<windows.h>
    #include<conio.h>
    #include<stdio.h>
    #include<cstdio>
    using namespace std;
    
    BOOL WINAPI HandlerRoutine(CTRL_CLOSE_EVENT);
    
    int main()
    {
    	SetConsoleCtrlHandler(CTRL_CLOSE_EVENT, FALSE);
    	getch();
    }
    

    bis jetzt hat dieser Code überhaupt nichts an dem Verhalten des Programms beim Schließen bewirkt.

    im Gegenteil: es bewirkt sogar eine Fehlermeldung:

    error C2664: 'SetConsoleCtrlHandler': Konvertierung des Parameters 1 von 'int' in 'PHANDLER_ROUTINE' nicht möglich

    (ich Verwende Microsoft Visual C++ 2008 Express edition, Windows XP).

    wo schreibe ich jetzt da hin was er vor dem Schließen tun soll?



  • Du musst einen Pointer auf eine Funktion übergeben, die die Events verarbeitet.



  • wie geht das hier?
    vielleicht mal ein kuzes Codebeispiel?



  • caste einfach nach PHANDLER_ROUTINE

    SetConsoleCtrlHandler((PHANDLER_ROUTINE)CTRL_CLOSE_EVENT, FALSE);
    


  • // einfach ma von dir kopiert
    #include<iostream>
    #include<windows.h>
    #include<conio.h>
    #include<stdio.h>
    #include<cstdio>
    using namespace std;
    
    // Handler ;)
    // Zeigt deine MessageBox
    BOOL WINAPI HandlerRoutine(DWORD eventCode)
    {
      switch(eventCode)
      {
      case CTRL_CLOSE_EVENT:
        MessageBox(0, TEXT("Message Text"), TEXT("Message Title"), MB_OK | MB_ICONINFORMATION);
        break;
      }
      return TRUE;
    }
    
    // Handler einrichten und dann kannstes Fenster schliesen und gucken obs funzt^^
    int main()
    {
        SetConsoleCtrlHandler(HandlerRoutine, TRUE);
        getch();
    }
    


  • Melan schrieb:

    caste einfach nach PHANDLER_ROUTINE

    SetConsoleCtrlHandler((PHANDLER_ROUTINE)CTRL_CLOSE_EVENT, FALSE);
    

    Du sollst der Funtion "SetConsoleCtrlHandler" ne Funktion beim ersten Parameter übergeben, alles andere macht keinen Sinn... woher sollte Windows dann Wissen welcher Code ausgeführt werden soll??
    Du übergibst der SetConsoleCtrlHandler ne Funktion die auf alle möglichen Events der Konsole reagiert, bzw auf die die du abfangen willst.



  • vielen dank, das Codebeispiel von kalli funktioniertz super=)

    nur jetzt lässt sich das Fenster ´nur noch über prozess beenden schließen.
    kann man dem Programm irgendwie sagen dass es sich nach der Message box beenden soll?



  • ich habs jetzt selbst geschafft, einfach die cstdlib includen und mit
    exit(0); beenden

    Danke für die Hilfe!



  • andi01 schrieb:

    ich habs jetzt selbst geschafft, einfach die cstdlib includen und mit
    exit(0); beenden

    Danke für die Hilfe!

    Du weisst schon dass dann nicht alle deine C++ Objekte nicht zerstört werden?
    (zerstört wird nur was statisch/global instanziert wurde, und natürlich laufen über atexit() registrierte Handler, aber keine Destruktoren von dynamisch angelegten Objekten, oder von Objekten die irgendwo "auf dem Stack" instanziert wurden)



  • wie kann ich es dann besser beenden?
    eigentlich geht es ja nur darum das es sich überhaupt beendet nach der MessageBox.



  • Bei mir beendet sich das Programm perfekt^^
    Probiers mal mit "return FALSE" anstelle von "return TRUE;" und hau das exit raus



  • danke, ich habs jetzt mit return false probiert und es funktioniert=)

    da sich das Programm jetzt perfekt beendet wäre das Problem wohl gelöst.

    Danke nochmal für die Hilfe,
    Andreas.



  • Ich will dir hier nix einreden was in deinem Fall vielleicht völlig unnötig ist. Oft reicht ein exit(), obwohl dann eben viele Destruktoren nicht laufen. Oft *möchte* man sogar dass die nicht laufen.

    Wenn man allerdings den Ctrl+C Handler überschreibt, um ein Programm sauber beenden zu können, dann will man meist alles "kontrolliert beenden/niederfahren".
    Das macht man z.B. indem man ein Flag setzt und dann einen Event bzw. eine Condition-Variable signalisiert, und dann mit "return TRUE;" angibt, dass der Ctrl+C Event behandelt wurde.
    Das Programm läuft dann ganz normal weiter.

    Damit es sich auch beendet, baut man dann irgendwo Checks ein, die gucken ob das Flag gesetzt ist, und in dem Fall das Programm kontrolliert beenden. So kann man dann alle Objekte schön zerstören, alle Threads beenden, alles aufräumen, ggf. noch Einträge ins Logfile schreiben etc.

    Aber wie gesagt: oft ist das der totale Overkill.

    p.S.: statt "return FALSE;" kannst du gleich exit() machen - macht keinen Unterschied. "return FALSE;" bewirkt in dem Fall nur, dass der nächste Handler in der Kette auch noch aufgerufen wird, und der macht dann eben das exit(). Ob der das macht, oder du selbst, ist vollkommen egal.



  • ok, ich denke mal ich werde das mit dem return false so lassen.

    aber: ich habe schon versucht ein CTRL_C_EVENT zu definieren, bin aber daran gescheiter da ctrl+c die Anwendung sofort beendet, ohne irgendeine Chance für den Prozess noch etwas auszufühern.

    hier mal mein Code:

    // einfach ma von dir kopiert 
    #include<iostream> 
    #include<windows.h> 
    #include<conio.h> 
    #include<stdio.h> 
    #include<cstdio> 
    #include<cstdlib>
    using namespace std; 
    
    // Handler ;) 
    // Zeigt deine MessageBox 
    BOOL WINAPI HandlerRoutine(DWORD eventCode) 
    { 
      switch(eventCode) 
      { 
      case CTRL_CLOSE_EVENT: 
        MessageBox(0, TEXT("Schließen über X zugelassen"), TEXT("zulässiges Schließen"), MB_OK | MB_ICONINFORMATION); 
    	return FALSE;
        break; 
    
      case CTRL_C_EVENT:// hat aber keine chance, da strg+c den prozess abschießt ehe er reagieren kann
    	  MessageBox(0, TEXT("Schließen über strg + C zulässig"), TEXT("zulässiges Schließen"), MB_OK);
    	  return FALSE;
    	  break;
      } 
      return TRUE; 
    } 
    
    // Handler einrichten und dann kannstes Fenster schliesen und gucken obs funzt^^ 
    int main() 
    { 
        SetConsoleCtrlHandler(HandlerRoutine, TRUE); 
        getch(); 
    }
    

    irgendwas scheine ich ja aber falsch zu machen, da sich das Programm ohen messageBox beendet. Wie müsste der Code denn richtig heißen?

    Danke schonmal,
    Andreas.



  • er.
    meinst du dass getch() nicht zurückkommt wenn du ctrl+c drückst?
    kleiner tip: windows führt den handler in einem eigenen thread aus, asynchron zu allem was sonst noch läuft.
    mach aus dem "getch()" mal ein "while (1) getch();", dann wirst du sehen dass es funktioniert.



  • danke, jetzt funktioniert auch das noch=)

    jetzt ist der code soweit fertig;

    danke nochmal,
    Andreas.


Log in to reply