rover Posted June 7, 2009 Posted June 7, 2009 OnAutoItExit() functionality for console appsthis example will stop Ctrl-C and Ctrl-Break from closing a console appthen run a cleanup function before exiting.can also call system 'EndProgram' EndNow/Cancel dialog for console Close, Log Off or ShutdownOS: Win 2000 and uptested on XP onlysome MSDN reference links:CTRL+C and CTRL+BREAK Signalshttp://msdn.microsoft.com/en-us/library/ms682541.aspxSetConsoleCtrlHandler Functionhttp://msdn.microsoft.com/en-us/library/ms686016(VS.85).aspxRegistering a Control Handler Functionhttp://msdn.microsoft.com/en-us/library/ms685049(VS.85).aspxexpandcollapse popup#AutoIt3Wrapper_Change2CUI=y If Not @Compiled Then Exit Global Const $CTRL_BREAK_EVENT = 1 Global Const $CTRL_C_EVENT = 0 Global Const $CTRL_CLOSE_EVENT = 2 Global Const $CTRL_LOGOFF_EVENT = 5 Global Const $CTRL_SHUTDOWN_EVENT = 6 Local $fCloseFlag = False Local $fCancelExit = False Local $line = "" ;Register control handler callback Local $hStub_CtrlHandler = DllCallbackRegister("_CtrlHandler", "long", "dword") Local $aRet = DllCall("Kernel32.dll", "int", "SetConsoleCtrlHandler", "ptr", DllCallbackGetPtr($hStub_CtrlHandler), "dword", 1) Local $file = FileOpen("con", 4) ConsoleWrite(@CRLF & "'Exit'/Ctrl-C/Ctrl-Break/Titlebar/Menu - Runs cleanup then exits: " & @CRLF) While 1 $line = BinaryToString(FileRead($file, 128)) If StringInStr($line, "exit", -1) <> 0 Then _Cleanup();type exit to close If $fCloseFlag Then _Cleanup() If $fCancelExit Then ;restart callback and console read functions $fCancelExit = False $file = FileOpen("con", 4) DllCall("Kernel32.dll", "int", "SetConsoleCtrlHandler", "ptr", DllCallbackGetPtr($hStub_CtrlHandler), "dword", 1) EndIf WEnd ;MSDN ;The system generates CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, and CTRL_SHUTDOWN_EVENT signals when the user closes the console, ;logs off, or shuts down the system so that the process has an opportunity to clean up before termination. ;Console functions, or any C run-time functions that call console functions, ;may not work reliably during processing of any of the three signals mentioned previously. ;The reason is that some or all of the internal console cleanup routines may have been called before executing the process signal handler. ;NOTE: you cannot call cleanup functions from the handler (won't run properly) for CTRL_C_EVENT and CTRL_BREAK_EVENT, ;set a flag and call cleanup functions from main loop. ;cleanup functions must be called from handler for CTRL_CLOSE_EVENT as app will exit after returning false from CTRL_CLOSE_EVENT message Func _CtrlHandler($dwCtrlType) Switch $dwCtrlType Case $CTRL_C_EVENT ConsoleWrite('Ctrl-C event: ' & $dwCtrlType & @CRLF);debugging only $fCloseFlag = True;cleanup function must be called from loop Return True; Return True prevents exit: block exit or set flag for cleanup before exit Case $CTRL_BREAK_EVENT ConsoleWrite('Ctrl-Break event: ' & $dwCtrlType & @CRLF) $fCloseFlag = True;cleanup function must be called from loop Return True; Return True prevents exit: block exit or set flag for cleanup before exit Case $CTRL_CLOSE_EVENT ;closing command window by titlebar button or menu: optionally run cleanup before exit or return to app if user cancels exit ;ConsoleWrite('Ctrl-Close event: ' & $dwCtrlType & @crlf);debugging only _Cleanup(True);cleanup function must be called from here $fCancelExit = True; if user selects cancel from system 'EndProgram' popup dialog box set flag to re-start required functions from main loop ;Return False; No XP popup cancel exit dialog ;(if slow functions called before this line then endprogram dialog box does not appear) Return True; XP popup cancel exit dialog (can continue app if user clicks dialog cancel button) ;CTRL+CLOSE Signal: http://msdn.microsoft.com/en-us/library/ms682535(VS.85).aspx ;Vista and Windows 2008 behaviour difference (comment by David Lowndes) ;Where the documentation currently says: ;"Return TRUE. In this case, no other handler functions are called, ;and a pop-up dialog box asks the user whether to terminate the process." ;This is correct for Windows XP, but by default Windows Vista and 2008 server do not show a dialog box, ;the process terminates with no further user interaction. Case $CTRL_LOGOFF_EVENT; User Log Off and Shutdown events ;inconsistent: sometimes exits before returning from cleanup function ;ConsoleWrite('Ctrl-Logoff event: ' & $dwCtrlType & @crlf);debugging only _Cleanup(True) ;for best responsiveness, do not call anything before next line if you want system endprogram dialog to postpone log off or shutdown ;(if slow functions called before this line then endprogram dialog box does not appear) Return True; XP popup cancel exit dialog (can continue app if user clicks dialog cancel button) ;Return False; No XP popup cancel exit dialog ;~ Case $CTRL_SHUTDOWN_EVENT; Not called for shutdown or restart, use log off ;~ ;ConsoleWrite('Ctrl-Shutdown event: ' & $dwCtrlType & @crlf);debugging only ;~ _Cleanup(True) ;~ Return False EndSwitch Return False EndFunc ;==>_CtrlHandler Func _Cleanup($iExitMode = False) FileClose($file) DllCall("Kernel32.dll", "int", "SetConsoleCtrlHandler", "ptr", 0, "dword", 0);remove control handler If $iExitMode Then Return; DllCallbackFree crashes app if called for CTRL_CLOSE_EVENT message DllCallbackFree($hStub_CtrlHandler) Beep(1000, 5) Exit EndFunc ;==>_Cleanup I see fascists...
Zedna Posted June 7, 2009 Posted June 7, 2009 AWESOME! five stars from me. Resources UDF ResourcesEx UDF AutoIt Forum Search
JRSmile Posted June 7, 2009 Posted June 7, 2009 works really well but i get a -1 critical error when starting the app with cmd.exe and clicking on menu or the [x] if i directly start the exe it works fine. best regards, JR. $a=StringSplit("547275737420796F757220546563686E6F6C75737421","") For $b=1 To UBound($a)+(-1*-1*-1)step(2^4/8);&$b+=1*2/40*µ&Asc(4) Assign("c",Eval("c")&Chr(Dec($a[$b]&$a[$b+1])));''Chr("a")&"HI" Next ;time_U&r34d,ths,U-may=get$the&c.l.u.e;b3st-regards,JRSmile; MsgBox(0x000000,"",Eval("c"));PiEs:d0nt+*b3.s4d.4ft3r.1st-try:-)
rover Posted June 7, 2009 Author Posted June 7, 2009 works really well but i get a -1 critical error when starting the app with cmd.exe and clicking on menu or the [x] if i directly start the exe it works fine. best regards, JR.Thanks Zedna, JRSmile Hi JRSmile what AutoIt version?, probably not relevant what OS? screenshot of dialog? background processes running? I assume that's the AutoIt error dialog and not the long windows exception dialog (running DllCallBackFree from the handler caused that one) maybe PM me a compiled script the Ctrl-C/Ctrl-Break blocking is the best performing of this API the MSDN remarks as I've included mention possible problems with the other messages. I've run this example as console app standalone or from cmd.exe from Run dialog or typed into existing cmd console Ctrl-C/Ctrl-Break/'Exit'/Menu and button close without a crash on 3 XP systems, one system does not have the popup endprogram dialog enabled (Don't remember where that option is set or if it is an option, maybe something is turned off or broken on that XP system) closing a cmd.exe window by X button or menu when the script is running will occasionally not return from the cleanup function before exiting. (this is only happening on one of the three XP systems) the CTRL_LOGOFF_EVENT message also has this problem. reliability of CTRL_CLOSE_EVENT and CTRL_LOGOFF_EVENT exit cleanup needs some work... I see fascists...
Teslafreak Posted June 8, 2009 Posted June 8, 2009 This is a tremendous help for me. 5 stars, thanks so much!
rover Posted June 9, 2009 Author Posted June 9, 2009 @Teslafreak, your welcome @JRSmile I can get the AutoIt Error Line -1 undeclared variable dialog, but only by placing a blocking MsgBox in Cleanup() (sleep doesn't even do it) the problem is the handler function is called in a new thread on each event. (creates a new thread for each event then destroys it on return) I did not pay too much attention to this and its consequences at first as my only programming experience is with the single thread dimension of AutoIt. so that limits the OnAutoItExit usefulness unless some inter thread code can allow functions called in Cleanup() for messages CTRL_CLOSE_EVENT and CTRL_LOGOFF_EVENT in the handler thread to work reliably with vars declared in the main thread. (CTRL_SHUTDOWN_EVENT message only sent if console app is a service, which requires RegisterServiceCtrlHandlerEx API) a least the Ctrl-C/Ctrl-Break blocking works o.k. I have to leave this for knowledgeable Win32 programmers to comment on. I see fascists...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now