Jump to content

OnAutoItExitRegister() issue


orbs
 Share

Recommended Posts

OnAutoItExitRegister() stopped working for one of my scripts, running on Windows 7 & 10. the registered function stopped executing upon exit. there were many complex modifications and i don't know when it stopped working so checking earlier versions would be troublesome. i did write this simple reproducer:

OnAutoItExitRegister('_OnExit')

HotKeySet('{F9}', '_UserExit')

DirCreate('C:\TEMP')
FileWriteLine('C:\TEMP\_OnExitTest.log', @HOUR & ':' & @MIN & ':' & @SEC & @TAB & 'start')

While True
    Sleep(60000)
    FileWriteLine('C:\TEMP\_OnExitTest.log', @HOUR & ':' & @MIN & ':' & @SEC & @TAB & 'checkup')
WEnd

Func _UserExit()
    Exit 9
EndFunc   ;==>_UserExit

Func _OnExit()
    FileWriteLine('C:\TEMP\_OnExitTest.log', @HOUR & ':' & @MIN & ':' & @SEC & @TAB & '@exitCode=' & @exitCode & @TAB & '@exitMethod=' & @exitMethod)
EndFunc   ;==>_OnExit

tested on Windows 7: it works. the registered function is executed at manual exit (from the tray menu, and by the assigned hotkey) and at shutdown (the script is running compiled). my original script, however, does not. so i'm starting to eliminate pieces until i figure out the difference between my full script and this reproducer. 

tested the reproducer on Windows 10: the registered function is executed if i exit the script manually. it does not execute at shutdown.

no issue with permissions - the script writes its "start" and "checkup" messages successfully. i even started it as a scheduled task with elevated SYSTEM account - same issue. nothing on the event logs.

any ideas?

 

Signature - my forum contributions:

Spoiler

UDF:

LFN - support for long file names (over 260 characters)

InputImpose - impose valid characters in an input control

TimeConvert - convert UTC to/from local time and/or reformat the string representation

AMF - accept multiple files from Windows Explorer context menu

DateDuration -  literal description of the difference between given dates

Apps:

Touch - set the "modified" timestamp of a file to current time

Show For Files - tray menu to show/hide files extensions, hidden & system files, and selection checkboxes

SPDiff - Single-Pane Text Diff

 

Link to comment
Share on other sites

That script works in my Win10, even on shutdown. Maybe for some reason, on your OS during shutdown, Windows kills your app instead of close it.

If you don't try a solution, it can be useful for you to catch shutdown messages and parse 'em.

Edited by j0kky
Link to comment
Share on other sites

correction: the reproducer shows the same issue (registered function is not executed at shutdown) on both Windows 7 and 10 (and clean VM of server 2012, see below), when run as a scheduled task as elevated SYSTEM account (similar condition as my production script. i even disabled the option "if the running task does not end when requested, force it to stop").

upon exit by Task Scheduler "End" command, @exitMethod=0.

when running manually:

upon exit by tray menu: @exitMethod=2

upon exit by hotkey: @exitMethod=1

this is all expected. however at shutdown, there is no indication at the log.

i also tried on a clean VM of Windows Server 2012 r2. this time even the Task Scheduler "End" command did not log the expected result! only manual exit is OK. i enabled History and i see the proper chain of events.

@j0kky,

can you elaborate on your shutdown message comment? i read it's about trapping and processing windows messages, but my production script is compiled as console, no GUI whatsoever (not even a tray menu).

Signature - my forum contributions:

Spoiler

UDF:

LFN - support for long file names (over 260 characters)

InputImpose - impose valid characters in an input control

TimeConvert - convert UTC to/from local time and/or reformat the string representation

AMF - accept multiple files from Windows Explorer context menu

DateDuration -  literal description of the difference between given dates

Apps:

Touch - set the "modified" timestamp of a file to current time

Show For Files - tray menu to show/hide files extensions, hidden & system files, and selection checkboxes

SPDiff - Single-Pane Text Diff

 

Link to comment
Share on other sites

I tested it only running manually with user rights, I don't know its behaviour if started by scheduled task nor with SYSTEM rights.

1 hour ago, orbs said:

no GUI whatsoever

Elaborating a shutdown message comment only needs an hide window which gives you its handle, this is a working example of intercepting shutdown, uncomment lines if you want to "block" it for a while.

;#Include <WinAPIEx.au3>

Global $hForm, $Msg

$hForm = GUICreate('MyGUI')
GUIRegisterMsg(0x0011, 'WM_QUERYENDSESSION')
GUISetState(@SW_HIDE)

;_WinAPI_SetProcessShutdownParameters(0x03FF)

While 1
    $Msg = GUIGetMsg()
WEnd

Func WM_QUERYENDSESSION($hWnd, $Msg, $wParam, $lParam)
    If $hWnd = $hForm Then
        ;_WinAPI_ShutdownBlockReasonCreate($hForm, 'something')
        ;Return False
        Return True
    EndIf
    Return 'GUI_RUNDEFMSG'
EndFunc   ;==>WM_QUERYENDSESSION

 

Edited by j0kky
Link to comment
Share on other sites

thanks @j0kky, i will test your example. please clarify:

instead of using OnAutoItExitRegister(), i need to put my "on exit" commands inside your WM_QUERYENDSESSION() function, before it returns True?

instead of creating my own GUI, can i use the handle for the AutoIt hidden window (as demonstrated in the example for AutoItWinGetTitle)? does this window even exist in console mode?

Signature - my forum contributions:

Spoiler

UDF:

LFN - support for long file names (over 260 characters)

InputImpose - impose valid characters in an input control

TimeConvert - convert UTC to/from local time and/or reformat the string representation

AMF - accept multiple files from Windows Explorer context menu

DateDuration -  literal description of the difference between given dates

Apps:

Touch - set the "modified" timestamp of a file to current time

Show For Files - tray menu to show/hide files extensions, hidden & system files, and selection checkboxes

SPDiff - Single-Pane Text Diff

 

Link to comment
Share on other sites

27 minutes ago, orbs said:

instead of using OnAutoItExitRegister(), i need to put my "on exit" commands inside your WM_QUERYENDSESSION() function, before it returns True?

Yes, remember general recommendation for processing message:

Warning: blocking of running user functions which executes window messages with commands such as "MsgBox()" can lead to unexpected behavior, the return to the system should be as fast as possible !!!

So, if you just need to write a line in a text file, no problem; but if you need more complex elaboration it would be better to set a global variable within WM_QUERYENDSESSION function, return and check for that flag in the main loop. Differently from other messages, WM_QUERYENDSESSION has another disadvantage: each elaboration you have to do, you must complete it as fast as possible, because the system is shutting down and you really have few time.

27 minutes ago, orbs said:

instead of creating my own GUI, can i use the handle for the AutoIt hidden window (as demonstrated in the example for AutoItWinGetTitle)? does this window even exist in console mode?

I suspected the existence but I didn't know about that hidden window :D Try for it and let me know!

Edited by j0kky
Link to comment
Share on other sites

using WM_QUERYENDSESSION does not behave well. using the very basic example at post #4, i just added a FileWriteLine before the Return True line. result: at shutdown, the system hangs for a few seconds, then briefly pops-up the screen about a process not closing (or something similar), then immediately shutdown. in any case, no line was written to file.

at least there is one plus to this - all test environments behave the same.

tested on visible GUI, AutoIt hidden window, running as user and as system - in all conditions, no line was written to file.

i'm still testing options, like using _WinAPI_SetProcessShutdownParameters in various ranges.

regardless, i would very much like to have OnAutoItExitRegister working again. even if i get WM_QUERYENDSESSION to work, and i obviously can manually call the exit routine upon user request, then the method of closing by ending the task is not covered. it is - or was, at least - detected by OnAutoItExitRegister (where @exitMethod=0).

Signature - my forum contributions:

Spoiler

UDF:

LFN - support for long file names (over 260 characters)

InputImpose - impose valid characters in an input control

TimeConvert - convert UTC to/from local time and/or reformat the string representation

AMF - accept multiple files from Windows Explorer context menu

DateDuration -  literal description of the difference between given dates

Apps:

Touch - set the "modified" timestamp of a file to current time

Show For Files - tray menu to show/hide files extensions, hidden & system files, and selection checkboxes

SPDiff - Single-Pane Text Diff

 

Link to comment
Share on other sites

Can you post bit of the code, few days ago i did something similar, and upon the event i can even manage to connect to a DB, update some records and return for like half an second, so writing a line to a file should not be a problem, at all.

Also, you can try and opening the file with FileOpen(), write to it with FileWriteLine() then close the file with FileClose(). Depending on your file, i believe it will be alot faster than passing the filename directly to FileWriteLine().

If your program is intended to write a file upon user's session end, you can just task schedule it, events that i use (and i know working) are

System\User32\1074 and system\winlogon\7002. (see attached screenshots 1 and 2). And for action i use the exe (stored in random folder of your choice, screenshot 3).

EDIT : i personally believe it's better to taskschedule the logout instead of having something waitining for the event to appear.

Screenshot 1

Spoiler

Screenshot_1.png

 

Screenshot 2

Spoiler

Screenshot_2.png

 

Screenshot 3

Spoiler

Screenshot_3.png

 

Edited by JustSomeone
i'm dumb, added some spoilers not to make the post a mile long ;)
Link to comment
Share on other sites

@JustSomeone,

48 minutes ago, JustSomeone said:

Can you post bit of the code

code using OnAutoItExitRegister() - see first post. code using WM_QUERYENDSESSION - see post #4, as i mentioned i just added a FileWriteLine (to an existing file, eliminated permissions issue).

 

50 minutes ago, JustSomeone said:

Also, you can try and opening the file with FileOpen(), write to it with FileWriteLine() then close the file with FileClose(). Depending on your file, i believe it will be alot faster than passing the filename directly to FileWriteLine().

FileWriteLine opens and closes a file if a file name is specified. this is clearly mentioned in the help.

as for the scheduling option: my production script is running as a scheduled task, run at startup, under the local SYSTEM account. it is constantly monitoring a specific input file, and when that file is generated (by another process), my script analyzes it, write some stats data into a report file, evacuates the input file, and logs the entire operation in a log file. the input file may be generated several times a minute, or none at all for hours. other than background monitoring, i have no way of knowing when the input file is generated, so scheduling it otherwise is of no use.

what i need to do on exit is simple - write a line to the log file saying it's exiting, at which time, and with what @exitCode and @exitMethod. then i want to rotate the log file, so the next time my script runs, it begins with a fresh log. this has proven very helpful for later analysis.

in case of crash, my script starts with checking the existence of a log file, and rotate it if it exists. this was supposed to be only for crash recovery, because the log should have been rotated on exit. so, although i do have a working solution for log rotation, i lost the info about the script exit conditions.

i know it should work; it did work for a while. now it doesn't, and it's not only my production script that is not working, it's the simple reproducer too.

 

1 hour ago, JustSomeone said:

i did something similar

did you use OnAutoItExitRegister() or WM_QUERYENDSESSION ? or task scheduling?

Signature - my forum contributions:

Spoiler

UDF:

LFN - support for long file names (over 260 characters)

InputImpose - impose valid characters in an input control

TimeConvert - convert UTC to/from local time and/or reformat the string representation

AMF - accept multiple files from Windows Explorer context menu

DateDuration -  literal description of the difference between given dates

Apps:

Touch - set the "modified" timestamp of a file to current time

Show For Files - tray menu to show/hide files extensions, hidden & system files, and selection checkboxes

SPDiff - Single-Pane Text Diff

 

Link to comment
Share on other sites

21 minutes ago, orbs said:

@JustSomeone

did you use OnAutoItExitRegister() or WM_QUERYENDSESSION ? or task scheduling?

I used pure task scheduling since i did not had an running proccess under the SYSTEM account since startup (i didn't need it). My mistake, i didn't properly read the entire thread. However, it's interesting for me so i'll watch the thread, and read bit more about the matter, if i come up with something, i will post it ;)

EDIT: I briefly remember something about GUI stuff (even fake ones) not working / not recieving calls at all under SYSTEM account, but i really can't remember the issue now. I will search for some links.

Edited by JustSomeone
Link to comment
Share on other sites

@orbs: "AutoitWinGetTitle" trick doen't work in this case, can you try to compile exatly this script and put it on the desktop, run it, then shutdown the OS and see what log.txt reports:

#Include <WinAPIEx.au3>

Global $hForm, $Msg, $vVar = 0

$hForm = GUICreate("My hidden GUI")
GUIRegisterMsg(0x0011, 'WM_QUERYENDSESSION')
GUISetState(@SW_HIDE)

FileWriteLine("log.txt", "Script started at " & @HOUR & ":" & @MIN & ":" & @SEC)

_WinAPI_SetProcessShutdownParameters(0x03FF)
_WinAPI_ShutdownBlockReasonCreate($hForm, 'Waiting for FileWriteLine')

While 1
    $Msg = GUIGetMsg()
    If $vVar = 1 Then
        FileWriteLine("log.txt", "Shutting down at " & @HOUR & ":" & @MIN & ":" & @SEC)
        _WinAPI_ShutdownBlockReasonDestroy($hForm)
        $vVar = 2
    EndIf
WEnd

Func WM_QUERYENDSESSION($hWnd, $Msg, $wParam, $lParam)
    If ($hWnd = $hForm) And (Not $vVar) Then
        $vVar = 1
        Return False
    ElseIf ($hWnd = $hForm) And ($vVar = 2) Then
        Return True
    EndIf
    Return 'GUI_RUNDEFMSG'
EndFunc   ;==>WM_QUERYENDSESSION

In my system it works.

Edited by j0kky
Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...