Steph Posted February 16, 2005 Share Posted February 16, 2005 I've a couple of scripts which sit running permanently in the tray (thanks Holger). When you shutdown or log off I want them to restore certain settings - is there any way to detect that Windows is shutting down or the user is logging off? I was hoping OnAutoItExit() would help, but the following only seems to work when you choose 'Exit' from the tray. while 1 sleep(1000) WEnd Func OnAutoItExit() MsgBox(64, "Bye", "Going going ...") EndFunc I know this has been mentioned before, but I was wondering if there were any events I can trap using the GUI stuff which Windows sends to all running applications... Thanks Steph Link to comment Share on other sites More sharing options...
Alterego Posted February 17, 2005 Share Posted February 17, 2005 Well it's sort of hacky, but you could run your program as a service, with the idea in mind that Windows will shut down other programs before your service (not sure if thats the case, but sounds reasonable). Then you could use ProcessExists to monitor a program that will never be closed unless windows is shutting down (AIM, trillian, whatever for example). If your program sees AIM is not running, you can stop the windows shutdown by typing 'shutdown -a' at the command line. Then do your cleanup, and use Shutdown() to finish... This dynamic web page is powered by AutoIt 3. Link to comment Share on other sites More sharing options...
Alterego Posted February 17, 2005 Share Posted February 17, 2005 Alternatively just write a program which contains something like Do Sleep(50000) Until 1 = 0 as a dummy process to poll for shutdown. If it gets closed...there you have it! This dynamic web page is powered by AutoIt 3. Link to comment Share on other sites More sharing options...
ZenKensei Posted February 17, 2005 Share Posted February 17, 2005 Steph, Found the following on www.myitforum.com (it assumes your running Windows 2000 or later):You can open the local Group Policy editor. Or if you need to automate this, then here's a totally unsupported method that may work. Copy your script to %SystemRoot%\system32\GroupPolicy\Machine\Scripts\Shutdown Manually edit the %SystemRoot%\system32\GroupPolicy\Machine\Scripts\script.ini file It has the following format: [shutdown] 0CmdLine=browse.vbs 0Parameters= There's also the GPAnywhere tool from www.FullArmor.com which can be used to configure shutdown scripts.Don't let the talk of Group Policy Objects dissuade from trying this method, your computer doesn't have to be in an Active Directory environment, your simply setting a local group policy on that PC.ZK Link to comment Share on other sites More sharing options...
jdickens Posted February 17, 2005 Share Posted February 17, 2005 (edited) http://www.autoitscript.com/forum/index.ph...357entry58357I was suggested to try this but it doesn't work.If WinExists("Shut Down Windows") Then $ScRdrIsWanted = $FALSE;for my needs only in this example ExitLoop EndIfJ Edited February 17, 2005 by jdickens If I am too verbose, just say so. You don't need to run on and on. Link to comment Share on other sites More sharing options...
Blue_Drache Posted February 17, 2005 Share Posted February 17, 2005 Well... I believe there is a message "broadcasted" when the system is shutting down. If you can hear it, you can call "abort" shutdown windows api to stop it... how to hear the message?Lar.<{POST_SNAPBACK}>Well, since Larry spoke up, I'm guessing a DLL call would be able to find the broadcast message...since all windows programs SHOULD hear the message (though I'm sure, not all DO) and thereby run though whatever they need to do to close gracefully before windows just outright KILLS the process. Lofting the cyberwinds on teknoleather wings, I am...The Blue Drache Link to comment Share on other sites More sharing options...
Steph Posted February 17, 2005 Author Share Posted February 17, 2005 Well, since Larry spoke up, I'm guessing a DLL call would be able to find the broadcast message...since all windows programs SHOULD hear the message (though I'm sure, not all DO) and thereby run though whatever they need to do to close gracefully before windows just outright KILLS the process. <{POST_SNAPBACK}>I've assumed there is some sort of message sent to all programs, but wasn't sure how to 'hear' it. Is there anybody who can suggest what DLL call to use and how (pretty please)?Steph Link to comment Share on other sites More sharing options...
Andre Posted February 17, 2005 Share Posted February 17, 2005 Hi, i've found this.... 'There's a message that you get sent when the system is shutting down, WM_QUERYENDSESSION. As much as I hate using native Win32 functions or message handling in a Windows Forms app, there doesn't appear to be any other way to catch a system shutdown event than to use this. ' Andre What about Windows without using AutoIt ?It would be the same as driving a car without an steering Wheel! Link to comment Share on other sites More sharing options...
Valik Posted February 17, 2005 Share Posted February 17, 2005 Hi,i've found this....'There's a message that you get sent when the system is shutting down, WM_QUERYENDSESSION. As much as I hate using native Win32 functions or message handling in a Windows Forms app, there doesn't appear to be any other way to catch a system shutdown event than to use this. 'Andre<{POST_SNAPBACK}>Following up on this. There's no direct path to get the actual message. PeekMessage(), which is the API function you must use requires a structure to work. However, it also supports filtering. If you filter all messages except WM_QUERYENDSESSION, then you can trap the event without worrying about the actual MSG structure. Link to comment Share on other sites More sharing options...
SlimShady Posted February 17, 2005 Share Posted February 17, 2005 I knew this was an impossible task. Also because you would have to keep checking if the message is sent. Which means there's very little time to do anything else. OR, you have a seperate script that listens for the message. I don't request anything I'm just sharing info. Link to comment Share on other sites More sharing options...
Valik Posted February 17, 2005 Share Posted February 17, 2005 Impossible? Its possible to miss the message on occasion, but I believe it's quite far from impossible. Link to comment Share on other sites More sharing options...
lupusbalo Posted February 17, 2005 Share Posted February 17, 2005 (edited) Just an idea: "do it the other way " Instead of using the "windows shutdown" use your own script:e.g. you will then use this "My Shutdown"in My Shutdown (or whatever it is), - you can do you own stuff first (end other scripts or programs, save files , Kill other windows, Close other processes etc... ) - then use "Shutdown" builtin AutoIt function to actually close the system (or restart or ....)Anyway, there will still be a pending problem - i also have - and which i couldn't find a way thru:AutoIt "ProcessClose" actally KILL the process, which is not fair if it should do some housekeeping before Closing/Exiting.No problem if there is a window associated, but sometimes there's no (or i couldn't find it) or you cannot "Exit" from this window but only from "system tray menu" (that's the case for firewall, resident backup sofware etc...).I found no easy way, yet , to activate "system tray menus" from a script.EDIT> to be more specific, up to now ifound no way to "send" a "Clean Close" message to programs such as ZoneAlarm, NeroBackItUp, Hotsync, K9... <EDIT Edited February 17, 2005 by lupusbalo Link to comment Share on other sites More sharing options...
Blue_Drache Posted February 17, 2005 Share Posted February 17, 2005 Following up on this. There's no direct path to get the actual message. PeekMessage(), which is the API function you must use requires a structure to work. <{POST_SNAPBACK}> PeekMessage() ??? Is that a new function in the betas? Or just C(++)? Lofting the cyberwinds on teknoleather wings, I am...The Blue Drache Link to comment Share on other sites More sharing options...
Valik Posted February 17, 2005 Share Posted February 17, 2005 There is no beta at the moment. It's an API function, which means its something that will have to be called via DllCall(). Link to comment Share on other sites More sharing options...
Steph Posted February 17, 2005 Author Share Posted February 17, 2005 Thanks for the suggestions, I'm trying the PeekMessage route, this is what I've got - it doesn't work, just sits there. It's probably something I'm doing - so if someone with more experience with the Windows API and DLL calls can have a look that would be great. ; See http://www.mentalis.org/apilist/PeekMessage.shtml Const $PM_NOREMOVE = 0 Const $WM_QUERYENDSESSION = 17 $handle=DllOpen("user32.dll") Dim $dummy[200], $ret[200] while 1 ; (lpMsg As MSG, ByVal hwnd As Long, ByVal wMsgFilterMin As Long, ByVal wMsgFilterMax As Long, ByVal wRemoveMsg As Long) As Long $ret=DllCall($handle, "long", "PeekMessage", "ptr", $dummy, "long" , 0, "long" , $WM_QUERYENDSESSION, "long", $WM_QUERYENDSESSION, "long", $PM_NOREMOVE) If $ret[0] <> 0 Then MsgBox(64, "Bye", "Time to go..", 2) Exit EndIf Sleep(100) WEnd Steph Link to comment Share on other sites More sharing options...
Valik Posted February 17, 2005 Share Posted February 17, 2005 (edited) Larry, it doesn't matter, you can filter out all other messages (Except WM_QUIT). So then it should only fire on any message within the filter range (And WM_QUIT). That means the structure can be totally ignored since only two messages will cause a non-zero return value.Edit: Steph, just as an experiment, make the first paramter "str" instead of "ptr". Making it "str" will give some memory for the MSG structure to be written to. This _might_ be the reason for it not working. This is just a guess, though. Edited February 17, 2005 by Valik Link to comment Share on other sites More sharing options...
this-is-me Posted February 17, 2005 Share Posted February 17, 2005 Not sure if you are looking external to au3 or internal, but there are a couple of free programs to do that:http://www.google.com/search?hl=en&lr=&saf...down+stopper%22The one I use is here:http://www.snapfiles.com/download/dlshutdownstop.htmlIt can notify and even run a program (autoit3.exe anyone?) when there is a shutdown attempt made. Who else would I be? Link to comment Share on other sites More sharing options...
Valik Posted February 18, 2005 Share Posted February 18, 2005 closest I could come is to get a return by using "int_ptr" for the msg structure instead of "str". But the PeekMessage never finds the WM_QUERYENDSESSION message... I can get other messages (i don't know which because I don't have a msg structure to look at) but when I filter for just the wm_queryendsession msg... no lucky...Lar.<{POST_SNAPBACK}>Larry, it wasn't about getting something to read, it was about avoiding any internal errors where the function demanded a non-null pointer be passed. I know that a couple of the Service-related API functions require a block of memory or they fail. So in those cases, passing a "str" instead of a "ptr" causes them to work. The actual parameter is irrelevant, however, the function demands it be non-null. Since it's still failing, it might just be that WM_QUERYENDSESSION isn't something PeekMessage() will find (By design). Link to comment Share on other sites More sharing options...
jdickens Posted February 18, 2005 Share Posted February 18, 2005 Not sure if this will help. This is over my head. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/system_shutdown_functions.asp indicates many flavors of HOW to shut down the system from C; perhaps one among you can figure out how to detect if this message has been initiated, or how to affect the "priveleges" (MS terminology) of the AutoIt prog. J If I am too verbose, just say so. You don't need to run on and on. Link to comment Share on other sites More sharing options...
Steph Posted February 18, 2005 Author Share Posted February 18, 2005 Thanks again for everyone's interest, here's my second go ...; See http://www.mentalis.org/apilist/PeekMessage.shtml #include <GUIConstants.au3> #Include <date.au3> Const $PM_NOREMOVE = 0 Const $PM_REMOVE = 1 Const $WM_QUERYENDSESSION = 17 $handle=DllOpen("user32.dll") if $handle = -1 then msgbox(64,"Error!","Didn't open DLL!",2) EndIf Dim $dummy[200], $ret[200] $window = GUICreate("Main window", 400, 400) $edit = GUICtrlCreateEdit("", 10, 10, 380, 380, $ES_READONLY + $ES_AUTOVSCROLL) GUISetState() $old = -1 while 1 ; (lpMsg As MSG, ByVal hwnd As Long, ByVal wMsgFilterMin As Long, ByVal wMsgFilterMax As Long, ByVal wRemoveMsg As Long) As Long $ret=DllCall($handle, "long", "PeekMessage", "str", $dummy, "long" , $window, "long" , 0, "long", 1000, "long", $PM_NOREMOVE) if @error = 1 Then msgbox(64, "Error!","Error in DllCall",2) EndIf if $old<>$ret[0] Then GUICtrlSetData($edit, _NowTime() & ": Ret[0] is " & $ret[0] & @crlf, 1) $old=$ret[0] EndIf WEnd... this seems to capture some messages (PeekMessage returns nonzero), but can't tell what and when I filter for WM_QUERYENDSESSION I don't get anything. Larry did you do something like this to get a return of some sort? Reading from jdickens link to ExitWindows does suggest that WM_QUERYENDSESSION is sent to the 'main window' of each application - so I created a window to pass in the call to PeekMessage - is this the main window or is it somewhere else? Another possibility is that I'm not checking the message queue quick enough so I took the 'sleep' out - no joy. The more likely possibility is that I'm straining the limits of my knowledge of Windows and am barking up the wrong tree. Any [further] ideas?Steph Link to comment Share on other sites More sharing options...
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