Seite 1 von 1

Behandlung von #CTRL_CLOSE_EVENT wird (teilweise) ignoriert

Verfasst: 18.11.2014 11:36
von Shamos
Hallo Gemeinde,

nachfolgendes Code-Beispiel sollte dazu dienen mir zu demonstrieren wie ich
irgendwelche Ereignisse abfangen kann, ohne das sich das Programm beendet,
sofern ich das im Programmcode selbst nicht auf saubere Weise herbeiführe.

Auf diese Weise möchte ich u.A. sicherstellen das ich nicht irgendwann einmal
z.B. während eines Übertragunsprozesses oder Schreib/Lese-Prozesses dann ein
unwillkommener Programmabbruch eintritt, welcher durch den Benutzer gerbeigeführt wurde.
Sei es nun durch CTRL+C oder durch das klicken eines [ X ] auf das Consolen-Fenster.
Zum anderen habe ich dann hiermit immer eine maximale Programm-Kontrolle.

Leider funktioniert das nicht so ganz, da sich das Programm trotz das ich das Event
#CTRL_CLOSE_EVENT abgefangen habe, trotzdem beendet und das mit einer Fehlermeldung
des Debuggers "Das mit dem Debugger getestete Executeable endete unerwartet"
was ja mal gar nicht angehen darf, da ich in einer Endlosschleife bin.

Nur wieso ist das so, und wieso wird mein Event nicht wie erwartet behandelt,
sprich, wieso wird mein Programm unerwartet beendet obwohl ich doch alle Events
abgefangen habe, um individuell darauf einzugehen, bevor ich das Ende des
Programms selbt herbeiführe, sofern ich das will?

Code: Alles auswählen

Procedure ControlHandler(fdwCtrlType)

	Beep_(5000,80) 
	Beep_(880,80) 
	Beep_(2000,80) 

	Select fdwCtrlType
	
		Case #CTRL_C_EVENT
			Debug "ctrl-c"
			;ProcedureReturn #True
		
		Case #CTRL_CLOSE_EVENT
			; hier Programm 2 schliessen
			Debug "close"
			CloseConsole()
			;ProcedureReturn #True
		
 		Case #CTRL_BREAK_EVENT
 			Debug "break"
 			;ProcedureReturn #True
 					
		Default
			Debug "Unbehandelter CTRL-TYPE:"+Str(fdwCtrlType)
			;ProcedureReturn #True

	EndSelect
	ProcedureReturn #True

EndProcedure

OpenConsole()
ConsoleColor(0,15)
ConsoleLocate(10,12)
PrintN("this is a test")
SetConsoleCtrlHandler_(@ControlHandler(), #True)

Repeat
	Delay(1)
ForEver 

Re: Behandlung von #CTRL_CLOSE_EVENT wird (teilweise) ignori

Verfasst: 18.11.2014 12:01
von Danilo
CTRL+C kann man ja ausschalten: SetConsoleCtrlHandler_(0, #True).

Für den Rest (User loggt sich aus, Windows wird herunter gefahren, Console wird vom User geschlossen, Process wird über TaskManager beendet usw.) gibt es
ja Deinen HandlerCallback. Da solltest Du Deine Schreib/Lese-Prozesse etc. sauber beenden, und dann das Programm, entsprechend dem Wunsch, beenden.
Der Control-Handler ist nicht dafür da, diese Abbrüche zu verhindern.

Siehe MSDN: HandlerRoutine callback function
The CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, and CTRL_SHUTDOWN_EVENT signals
give the process an opportunity to clean up before termination. A HandlerRoutine can perform any
necessary cleanup, then take one of the following actions:
* Call the ExitProcess function to terminate the process.
* Return FALSE. If none of the registered handler functions returns TRUE, the default handler terminates the process.
* Return TRUE. In this case, no other handler functions are called and the system terminates the process.
Statt ExitProcess_() nimmst Du in PB besser 'End', nach dem Du aufgeräumt hast.
Dann räumt auch PB seinen Teil auf und kann sich selbst sauber beenden, statt vom System abgeschossen zu werden.

Re: Behandlung von #CTRL_CLOSE_EVENT wird (teilweise) ignori

Verfasst: 18.11.2014 12:13
von Shamos
Hallo und danke erst mal Danilo für deine Antwort.

Ich hab es mir schon fast gedacht, nachdem ich nochmal etwas darüber sinniert habe.
Daher hab ich das nun wie folgt abgeändert, so gbts dann auch keine Kopfschmerzen mehr.
Gleichwohl man von aussen her, durch den vom Programm zurückgegebenen Feherlcode 255,
noch auf das erzwungene Beenden des Programms reagiert werden kann, falls nötig/erwünscht.

Code: Alles auswählen

Procedure ControlHandler(fdwCtrlType)
	Beep_(5000,80) 
	Beep_(880,80) 
	Beep_(2000,80) 
	Select fdwCtrlType
	
		Case #CTRL_C_EVENT
			Debug "ctrl-c"
		
		Case #CTRL_BREAK_EVENT
 			Debug "break"

;  	Case #CTRL_CLOSE_EVENT
;  	Case #CTRL_LOGOFF_EVENT
;  	Case #CTRL_SHUTDOWN_EVENT
		Default
			Debug "Erzwungenes Programmende durch Benutzer/System : CTRL-TYPE="+Str(fdwCtrlType)
			End 255 ; 

	EndSelect
	ProcedureReturn #True

EndProcedure

OpenConsole()
ConsoleColor(0,15)
ConsoleLocate(10,12)
PrintN("this is a test")
SetConsoleCtrlHandler_(@ControlHandler(), #True)


Repeat
	Delay(1)
ForEver