Behandlung von #CTRL_CLOSE_EVENT wird (teilweise) ignoriert

Anfängerfragen zum Programmieren mit PureBasic.
Shamos
Beiträge: 32
Registriert: 12.11.2014 09:44

Behandlung von #CTRL_CLOSE_EVENT wird (teilweise) ignoriert

Beitrag 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 
Windows 8.1 x64 | PureBasic 5.31 x64 | Dell Inspiron 3847 | i5-4440 3.1Ghz | 8GB DDR3 | Nvidia Geforce 625
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Behandlung von #CTRL_CLOSE_EVENT wird (teilweise) ignori

Beitrag 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.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Shamos
Beiträge: 32
Registriert: 12.11.2014 09:44

Re: Behandlung von #CTRL_CLOSE_EVENT wird (teilweise) ignori

Beitrag 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 
Windows 8.1 x64 | PureBasic 5.31 x64 | Dell Inspiron 3847 | i5-4440 3.1Ghz | 8GB DDR3 | Nvidia Geforce 625
Antworten