Sign in to follow this  
Followers 0
Jeemo

Mimic this shutdown blocker via AutoIT?

24 posts in this topic

#1 ·  Posted (edited)

There is a utility called Shutdown Monitor that prevents users from logging off or shutting down as long as a specified process is running. A quote from the site:

After you start Shutdown Monitor, it tells windows that it was one of the first programs that was started on the PC, so it will be the first notified if a user initiates a shutdown, reboot, log off etc. When it receives the shutdown notification it checks to see if the program you don't want the user to interrupt is still running, if it is, it pops up a msg box and tells the user why they can't shutdown and halts the shutdown process.

I really, really need to use what this program provides. I have an AutoIT script that blocks shutdown requests, but usually after the shutdown request has successfully killed processes that I need to remain running.

I have tried Shutdown Monitor and it works flawlessly. However, I cannot use it because when one tries to end the Windows session the program pops up a generic, poorly-written message that cannot be modified. If I were to pitch this solution to potentially broadcast the message to thousands of users I would surely be shot down.

Here is the code I have so far. I just need to modify it so that it can tell Windows to try shutting itself down first. Can anyone help?

GUIRegisterMsg($WM_QUERYENDSESSION, "Cancel_Shutdown")
GUICreate("PreventShutdownGUI")
GUISetSTate(@SW_HIDE)

Global $b_ShutdownInitiated = False

While 1
    If $b_ShutdownInitiated = True then
    EndIf
    If WinExists("Extracting Files") Then WinSetState("Extracting Files", "", @SW_HIDE)
    If WinExists($strAppMainWinTitle) Then WinSetState($strNalWinTitle, "", @SW_HIDE)
    sleep(10)
WEnd

Func Cancel_Shutdown($hWndGUI, $MsgID, $WParam, $LParam)
    $b_ShutdownInitiated = True
    MsgBox(48 + 8192 + 262144, "Installer", "Ending your user session has been disabled to allow the installation to complete." _
        & @CRLF & @CRLF & "You will be able to shutdown/reboot/logoff once the installation process has completed." , 8)

    Return False
EndFunc
Edited by Jeemo

An emoticon is worth a dozen words.

Share this post


Link to post
Share on other sites



oMBRa, I appreciate the tip but I've been to that page a few times and cannot find what I'm looking for there. The contents of that page are very relevant to the guts of my posted code, but I don't think there's anything in there that has any component of timing such as what I am looking for.


An emoticon is worth a dozen words.

Share this post


Link to post
Share on other sites

On Vista, ShutdownBlockReasonCreate should work


*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

EDIT: I see yout problem sorry...

Edited by oMBRa

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

I found a func to set the Shutdow level :D

$WM_QUERYENDSESSION = 0x11
GUIRegisterMsg($WM_QUERYENDSESSION, "Cancel_Shutdown")
GUICreate("PreventShutdownGUI")
GUISetSTate(@SW_HIDE)

; set highest notification level
If Not _SetProcessShutdownParameters(0xFFF) Then ; MSDN says maximum is 0x4FF, but it worked for me
    If Not _SetProcessShutdownParameters(0x4FF) Then ; MSDN says this is reserved for System, but worked for me
        _SetProcessShutdownParameters(0x3FF) ; highest not reserved number, if everything else does not work
    EndIf
EndIf

Global $b_ShutdownInitiated = False

While 1
    If $b_ShutdownInitiated = True then
        $b_ShutdownInitiated = False
        MsgBox(48 + 8192 + 262144, "Installer", "Ending your user session has been disabled to allow the installation to complete." _
        & @CRLF & @CRLF & "You will be able to shutdown/reboot/logoff once the installation process has completed." , 8)
    EndIf
    sleep(10)
WEnd

Func Cancel_Shutdown($hWndGUI, $MsgID, $WParam, $LParam)
    $b_ShutdownInitiated = True
    ; DO NOT ADD A MSGBOX HERE
    ; Windows shows a not responding box after ~5 secs and allows to kill your app.
    Return False
EndFunc


Func _SetProcessShutdownParameters($dwLevel, $dwFlags=0)
    ; http://msdn.microsoft.com/en-us/library/ms686227%28VS.85%29.aspx
    ; Prog@ndy
    Local $aResult = DllCall("Kernel32.dll", "int", "SetProcessShutdownParameters", "dword", $dwLevel, "dword", $dwFlags)
    If @error Then Return SetError(1,0,0)
    Return $aResult[0]
EndFunc
Edited by ProgAndy
1 person likes this

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites

Friggin' sweet! I'll give that a shot and get back to you. Thanks either way for your efforts.


An emoticon is worth a dozen words.

Share this post


Link to post
Share on other sites

Prog@ndy, I must tip my hat to you. I'm not sure if I would have ever found that ProcessShutdownParameters component that did the trick - if I were to have found it, it would not have been soon. I implemented the changes you added and it now works perfectly. Thank you so much.

Jeemo


An emoticon is worth a dozen words.

Share this post


Link to post
Share on other sites

Wow, that function is really cool :D

Share this post


Link to post
Share on other sites

Hah cool! One problemo...

I'm on vista and this doesn't do squat. I start it and make sure it gets a return value of 1(Said 0 means something failed). I click logoff and it just ends the application; logs me off. Tried the full shutdown and it didn't do anything either.

Vista the problem?

Share this post


Link to post
Share on other sites

Confirmed, tried on my virtualbox Vista SP2 and it doesn't stop the shutdown (or show the MsgBox)

I tried it compiled and with #RequireAdmin

Share this post


Link to post
Share on other sites

On Vista, ShutdownBlockReasonCreate should work

Confirmed, tried on my virtualbox Vista SP2 and it doesn't stop the shutdown (or show the MsgBox)

I tried it compiled and with #RequireAdmin

Ii already posted a solution for Vista and 7 :D

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

Ii already posted a solution for Vista and 7 :D

Doh /smackself.

Thanks!

$WM_QUERYENDSESSION = 0x11
GUIRegisterMsg($WM_QUERYENDSESSION, "Cancel_Shutdown")
$Hwnd = GUICreate("PreventShutdownGUI")
GUISetSTate(@SW_SHOW)


_ShutdownBlockReasonCreate($hwnd, "Sorry! you lose!")
TrayTip("Shutdown", "Denied shutdown for 15 seconds", 20)
Sleep(15000)
_ShutdownBlockReasonDestroy($hwnd)


Func _ShutdownBlockReasonCreate($Hwnd, $wStr)
    ; http://msdn.microsoft.com/en-us/library/ms...28VS.85%29.aspx
    ; Prog@ndy
    Local $aResult = DllCall("User32.dll", "int", "ShutdownBlockReasonCreate", "hwnd", $Hwnd, "wstr", $wStr)
    If @error Then Return SetError(1,0,0)
    Return $aResult[0]
EndFunc

Func _ShutdownBlockReasonDestroy($Hwnd)
    Local $aResult = DllCall("User32.dll", "int", "ShutdownBlockReasonDestroy", "hwnd", $Hwnd)
    If @error Then Return SetError(1,0,0)
    Return $aResult[0]
EndFunc

Func Cancel_Shutdown($hWndGUI, $MsgID, $WParam, $LParam)
    ; This HAS to be here to capture the endsession...
    ; DO NOT ADD A MSGBOX HERE
    ; Windows shows a not responding box after ~5 secs and allows to kill your app.
    Return False
EndFunc

Edit: Fixed it... Works now.

Edited by Szhlopp
1 person likes this

Share this post


Link to post
Share on other sites

Doh /smackself.

Thanks!

$WM_QUERYENDSESSION = 0x11
GUIRegisterMsg($WM_QUERYENDSESSION, "Cancel_Shutdown")
$Hwnd = GUICreate("PreventShutdownGUI")
GUISetSTate(@SW_SHOW)


_ShutdownBlockReasonCreate($hwnd, "Sorry! you lose!")
TrayTip("Shutdown", "Denied shutdown for 15 seconds", 20)
Sleep(15000)
_ShutdownBlockReasonDestroy($hwnd)


Func _ShutdownBlockReasonCreate($Hwnd, $wStr)
    ; http://msdn.microsoft.com/en-us/library/ms...28VS.85%29.aspx
    ; Prog@ndy
    Local $aResult = DllCall("User32.dll", "int", "ShutdownBlockReasonCreate", "hwnd", $Hwnd, "wstr", $wStr)
    If @error Then Return SetError(1,0,0)
    Return $aResult[0]
EndFunc

Func _ShutdownBlockReasonDestroy($Hwnd)
    Local $aResult = DllCall("User32.dll", "int", "ShutdownBlockReasonDestroy", "hwnd", $Hwnd)
    If @error Then Return SetError(1,0,0)
    Return $aResult[0]
EndFunc

Func Cancel_Shutdown($hWndGUI, $MsgID, $WParam, $LParam)
    ; This HAS to be here to capture the endsession...
    ; DO NOT ADD A MSGBOX HERE
    ; Windows shows a not responding box after ~5 secs and allows to kill your app.
    Return False
EndFunc

Edit: Fixed it... Works now.

How to get this to run a program at shutdown ??

I have tryed to get it to run a backupprogram, but seems like it dont want to execute exe files af system shutdown (using windows 7 rc7100)

Regards

/Rex

Share this post


Link to post
Share on other sites

hi can this be altered to stop standby would be usefull for a proogram for my laptop if somebody shuts the lid

Share this post


Link to post
Share on other sites

hi can this be altered to stop standby would be usefull for a proogram for my laptop if somebody shuts the lid

Here you go:

;Standby
#include <date.au3>
Global $WM_POWERBROADCAST      = 536
Global $PBT_APMRESUMESUSPEND  =  0x0007
Global $PBT_APMRESUMESTANDBY  =  0x0008
Global Const $BROADCAST_QUERY_DENY = 0x424D5144

$hGUI       = GUICreate("Test", 100, 100,1,1)
GUIRegisterMsg($WM_POWERBROADCAST, "Standby")
While 1
 Sleep(100000)
WEnd

Func Standby($hWnd, $Msg, $wParam, $lParam)
    ConsoleWrite(_NowTime() & ": " & $wParam & " "&$lParam & "Attempted standby"& @LF)
    Return $BROADCAST_QUERY_DENY    ;Tells Windows to pound sand
EndFunc

The easiest method is to change the settings so closing the lid doesn't start standby

XP instructions: Control Panel-> Power options->Advanced->"When I close the lid of my portable computer"

I ended up coming up with this program because as a limited access user Windows wasn't respecting my power settings. Eventually I found a way to give limited users permissions to change power settings.

Share this post


Link to post
Share on other sites

thanks this is really usefull

Share this post


Link to post
Share on other sites

Can you explain how this script works in detail?

Does it call the function SetProcessShutdownParameters to block the shutdown?

I found a func to set the Shutdow level :D

$WM_QUERYENDSESSION = 0x11
GUIRegisterMsg($WM_QUERYENDSESSION, "Cancel_Shutdown")
GUICreate("PreventShutdownGUI")
GUISetSTate(@SW_HIDE)

; set highest notification level
If Not _SetProcessShutdownParameters(0xFFF) Then ; MSDN says maximum is 0x4FF, but it worked for me
    If Not _SetProcessShutdownParameters(0x4FF) Then ; MSDN says this is reserved for System, but worked for me
        _SetProcessShutdownParameters(0x3FF) ; highest not reserved number, if everything else does not work
    EndIf
EndIf

Global $b_ShutdownInitiated = False

While 1
    If $b_ShutdownInitiated = True then
        $b_ShutdownInitiated = False
        MsgBox(48 + 8192 + 262144, "Installer", "Ending your user session has been disabled to allow the installation to complete." _
        & @CRLF & @CRLF & "You will be able to shutdown/reboot/logoff once the installation process has completed." , 8)
    EndIf
    sleep(10)
WEnd

Func Cancel_Shutdown($hWndGUI, $MsgID, $WParam, $LParam)
    $b_ShutdownInitiated = True
    ; DO NOT ADD A MSGBOX HERE
    ; Windows shows a not responding box after ~5 secs and allows to kill your app.
    Return False
EndFunc


Func _SetProcessShutdownParameters($dwLevel, $dwFlags=0)
    ; http://msdn.microsoft.com/en-us/library/ms686227%28VS.85%29.aspx
    ; Prog@ndy
    Local $aResult = DllCall("Kernel32.dll", "int", "SetProcessShutdownParameters", "dword", $dwLevel, "dword", $dwFlags)
    If @error Then Return SetError(1,0,0)
    Return $aResult[0]
EndFunc

Share this post


Link to post
Share on other sites

Can you explain how this script works in detail?

Does it call the function SetProcessShutdownParameters to block the shutdown?

_SetProcessShutdownParameters sets the shitdown notificationm level of the process. The higher this level is, the earlier the process is notified about a shutdown. I set it to a very high level, so less processes are informed about the shutdown before we cancel it.

On shutdown, $WM_QUERYENDSESSION is sent to our window, we respond to it with FALSE wich means, the shutdown process has to be interrupted wich prevents the system to shut down.

Btw: For Vista and later, there is a better method with _ShutdownBlockReasonCreate, so the method descripbed aboth should only be used on earlier OS.


*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites

#20 ·  Posted (edited)

So how would I set $WM_QUERYENDSESSION to true

Are you registering 0x11 to query your script every time a shutdown is called?

And then through that, it calls the cancel_shutdown function?

So if I wanted to have a conditional shutdown, I could put an in statement in the cancel_shutdown function and have it return true or false?

_SetProcessShutdownParameters sets the shitdown notificationm level of the process. The higher this level is, the earlier the process is notified about a shutdown. I set it to a very high level, so less processes are informed about the shutdown before we cancel it.

On shutdown, $WM_QUERYENDSESSION is sent to our window, we respond to it with FALSE wich means, the shutdown process has to be interrupted wich prevents the system to shut down.

Btw: For Vista and later, there is a better method with _ShutdownBlockReasonCreate, so the method descripbed aboth should only be used on earlier OS.

Edited by gte

Share this post


Link to post
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
Sign in to follow this  
Followers 0