Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Win7 adaptation of intercept hibernation script


  • Please log in to reply
37 replies to this topic
majstang
  • Members
  • 386 posts
  • Last active: Mar 27 2012 02:12 PM
  • Joined: 29 Aug 2008
Last try!
Still having the Chinese-character issue for a ShutdownBlockReason string. Anyone with Windows Vista/7 have this working, if so how do you imagine the DllCall to ShutdownBlockReasonCreate should look like to get a language one can understand? Have tried so many different combinations now without any success.

What is a marshal type of the pwszReason parameter and how would one go about translating that to ahk?

Hopefully there is somebody who knows this stuff.

Gui,+LastFound
hwnd:=WinExist()
DllCall("ShutdownBlockReasonCreate","Uint",hwnd,"Str",A_ScriptFullPath " is still running"


braynyac
  • Members
  • 14 posts
  • Last active: Oct 19 2010 08:08 PM
  • Joined: 06 Oct 2010
Majstang,

I am in the same boat...but need this for Server 2008 R2 (basically Windows 7 Server). Here is what I found: Autohotkey_L, and set the str to wstr in the line you provided above. Once I did that, everything is working =)

Hope this helps,

~Braynyac

majstang
  • Members
  • 386 posts
  • Last active: Mar 27 2012 02:12 PM
  • Joined: 29 Aug 2008

Majstang,

I am in the same boat...but need this for Server 2008 R2 (basically Windows 7 Server). Here is what I found: Autohotkey_L, and set the str to wstr in the line you provided above. Once I did that, everything is working =)

Hope this helps,

~Braynyac


Thanks, but I did manage to solve my issue at last on my own. The Chinese looking characters had nothing to do with the fact my script ended up on second place on the force shutdown UI (and therefor the the cancel of the force shutdown UI failed). Good to know though how to get rid of these funny looking curlicues :)

This line made my script to always be prioritized (first on force shutdown UI) and the script will always succeed:

DllCall("kernel32.dll\SetProcessShutdownParameters", UInt, 0x4FF, UInt, 0)

This is the whole script and it works great for HTPC use and looks awesome as well, thanks to SKAN:

#NoTrayIcon
#Persistent
SetTimer, RunBeforeShutdown, Off
Gui,+LastFound
hwnd:=WinExist()
DllCall("ShutdownBlockReasonCreate","Uint",hwnd,"Str",A_ScriptFullPath "is still running")
DllCall("kernel32.dll\SetProcessShutdownParameters", UInt, 0x4FF, UInt, 0)
OnMessage(0x11, "WM_QUERYENDSESSION")
Return

WM_QUERYENDSESSION(wParam, lParam)
  {
    static sdtry = 0
    ENDSESSION_Logoff = 0x80000000
    If (lParam & ENDSESSION_Logoff) ; User is logging off.
      EventType = Logoff
    Else     ; System is either shutting down or restarting. and
      EventType = Shutdown
    If (EventType = "Shutdown" and sdtry = 0)
     {
       SetTimer, RunBeforeShutdown, On
       Return false ; Tell the OS to Abort the Shutdown/Logoff.
     }
    Else If (EventType = "Shutdown" and sdtry = 1)
      Return true
  }


runBeforeShutdown:
SetTimer, RunBeforeShutdown, Off
SendInput, {ENTER}
Sleep, 2000
#SingleInstance, Force
SetWorkingDir %A_ScriptDir%  

FileDelete, demo.htm
FileAppend,
(
<html>
<body style="overflow:hidden">
<body bgcolor="#0033FF" leftmargin="1" topmargin="1">
<div align="Center"><p>
<font color="#FFFB02" face="Segoe Print" size="4"><br><b>
Your HTPC is about to be Closed Down.
<br>
You now have a chance to choose closedown method
<br>
or wait until default method gets choosen for you</b>
</p>
<font face="Segoe Print" size="5"><b>
<script type="text/javascript">
var countDownInterval=20; 
var countDownTime=countDownInterval+1; 
function countDown(){ 
countDownTime--; 
if (countDownTime <=0){ 
countDownTime=countDownInterval; 
clearTimeout(counter); 
//window.location=""; 
return 
} 
if (document.getElementById) //else if NS6+ 
document.getElementById("countDownText").innerHTML=countDownTime+" ";
else if (document.layers){ //CHANGE TEXT BELOW TO YOUR OWN 
document.c_reload.document.c_reload2.document.write('<b id="countDownText">'+countDownTime+' </b> seconds') 
document.c_reload.document.c_reload2.document.close() 
} 
counter=setTimeout("countDown()", 1000); 
} 

function startit(){ 
if (document.getElementById) //CHANGE TEXT BELOW TO YOUR OWN 
document.write('<b id="countDownText">'+countDownTime+' </b> seconds') 
countDown() 
} 

if (document.getElementById) 
startit() 
else 
window.onload=startit 
clearTimeout ( countDownTime );
</script>
</font></b>
</div>
</body>
</html>
)
, demo.htm


URL=file:///%A_ScriptDir%\demo.htm
Options := "Buttons=Hibernate/Standby/Shutdown/Restart/Cancel, HtmW=580, HtmH=200, BDefault=1, DlgBgColor=0xEE0000, DlgTopmost=1, TimeOut=20, Title=System Closedown in 20 seconds, DlgStyle=NoFrame"

Sel := HtmDlg( URL, "", Options )

if (Sel = 1)
  {
   DllCall("PowrProf\SetSuspendState", "int", 1, "int", 0, "int", 0)
   Return
  }
else if (Sel = 2)
  {
   DllCall("PowrProf\SetSuspendState", "int", 0, "int", 0, "int", 0)
   Return
  }
else if (Sel = 3)
  {
   Process, Close, dvbviewer.exe
   Shutdown, 1
   ExitApp
   Return
  }
else if (Sel = 4)
  {
   Process, Close, dvbviewer.exe
   Shutdown, 2
   ExitApp
   Return
  }
else if (Sel = 5)
  {
   hibernate = 0
   Return
  }

DllCall("ShutdownBlockReasonDestroy","Uint",hwnd)
Return                                                 ; // end of auto-execute section //

;#Include HtmDlg.ahk ; You may copy/Paste HtmDlg() Instead
HtmDlg( _URL="", _Owner=0, _Options="", _ODL="," ) {     ; HTML DialogBox v0.57 -- by SKAN
; Topic: www.autohotkey.com/forum/viewtopic.php?t=60215    CD:09-Jul-2010 | LM:05-Aug-2010
; Credit: WebControl Demo by Sean - www.autohotkey.com/forum/viewtopic.php?p=103987#103987

Static _hInst,_hDLG,_DlgP,_B$,_B$L,_pIWEB,_pV,_DlgT,CliC, HtmF=0,_Brush=0,   BDef=1,BEsc=0

 If ( A_EventInfo = 0xCBF ) {                                   ; nested Callback Function
   hWnd := _URL,  uMsg := _Owner,  wP := _Options,  lP := _ODL

   If ( uMsg=0x112 && wP=0xF060 )                               ; WM_SYSCOMMAND & SC_ClOSE
     Return DllCall( "DestroyWindow", UInt,_hDLG ) | ( BDEf:=BEsc )

   If ( uMsg=0x111 && (wP>>16)=0 )                              ; WM_COMMAND & BN_CLICKED
     Return DllCall( "DestroyWindow", UInt,_hDLG ) | ( BDef := (wP=2) ? BEsc : wP-100  )

   If ( uMsg=0x007 && HtmF=0 )                                  ; WM_SETFOCUS
     Return DllCall( "SetFocus", UInt,DllCall( "GetDlgItem", UInt,_hDLG, UInt,100+BDEF ) )

   If ( uMsg=0x201 && CliC )                                    ; WM_LBUTTONDOWN
     Return DllCall( "DestroyWindow", UInt,_hDLG ) |  ( BDEf := 1 )

   If ( uMsg=0x136 && _Brush<>0 )                               ; WM_CTLCOLORDLG
     Return _Brush

   if ( uMsg=0x002 && hWnd=_hDLG )                              ; WM_DESTROY
     Return _Brush := DllCall( "DeleteObject", UInt,_Brush, UInt ) >> 32

 Return False
 }

 If ! ( _hInst ) {
 _hInst := DllCall( "GetModuleHandle", Str,A_IsCompiled ? A_ScriptFullpath : A_AhkPath )

 _DT := "61160CD3AFCDD0118A3EGC04FC9E26EZQ1GFFFFUCHC88GAZO9G9G1I4DG53G2H53G68G65G6CG6CG2H"
 . "44G6CG67ZL5V64K41G74G6CG41G78G57G69G6EK7BG38G38G35G36G46G39G36G31G2DG33G34G3H41G2DG31"
 . "G31G44G3H2DG41G39G36G42G2DG3H3H43G3H34G46G44G37G3H35G41G32G7DZS14V65KFFFF8ZP14V66KFFF"
 . "F8ZP14V67KFFFF8ZP14V68KFFFF8ZP14V69KFFFF8ZP14V6AKFFFF8ZP14V6BKFFFF8ZP14V6CKFFFF8ZP14V"
 . "6DKFFFF8P"

 Loop 20   ;  Decompressing Nulls : www.autohotkey.com/forum/viewtopic.php?p=198560#198560
  StringReplace,_DT,_DT,% Chr(70+21-A_Index),% SubStr("000000000000000000000",A_Index),All

 Loop % _B$L := VarSetCapacity( _B$, ( _DTLEN := StrLen(_DT) // 2 ), 0 )
  NumPut( "0x" . SubStr(_DT, 2*A_Index-1,2),_B$,A_Index-1,"Char" )  ; Creating Structure
 _pIWEB := &_B$, _pV := &_B$+16, _DlgT := &_B$+32   ; Relevant pointers to Structure

 DllCall( "GetModuleHandle", Str,"atl.dll" ) ? 0 : DllCall( "LoadLibrary", Str,"atl.dll" )
 DllCall( "atl\AtlAxWinInit" ),          _DlgP := RegisterCallback( A_ThisFunc,0,4,0xCBF )
 }

 VarSetCapacity( _W$,_B$L,0 ), DllCall( "RtlMoveMemory", UInt,&_W$, UInt,&_B$, UInt,_B$L )
 _pIWEB := &_W$, _pV := &_W$+16, _DlgT := &_W$+32         ; Relevant pointers to Structure

 Butt:="OK", BWid:=75, BHei:=23, BSpH:=5, BSpV:=8, BAli:=1, Slee:=-1, HtmC:=0, CliC:=0
 HtmD:=0, DlgT:=0, DlgN:=0, DlgX:="", DlgY:="", HtmW:=240, HtmH:=140, Left:=0, TopM:=0
 Loop, Parse, _Options, =%_ODL%, %A_Space%        ; Override Variables with user 'Options'
   A_Index & 1  ? (  __  := (SubStr(A_LoopField,1,1)="_") ? "_" : SubStr(A_LoopField,1,4))
                : ( %__% := A_LoopField )
 
 Cap  := DllCall( "GetSystemMetrics", UInt,4  ) ; SM_CYCAPTION    = Window Caption
 Frm  := DllCall( "GetSystemMetrics", UInt,7  ) ; SM_CXFIXEDFRAME = Window Frame

 NumPut( HtmC<>0 ? 0x200 : 0x0, _W$, 32+68 ), DlgD := DlgD ? 0x8000000 : 0x0
 FonS ? NumPut( FonS < 8 ? 8 : ( FonS > 14 ? 14 : FonS ), _W$, 64, "UShort" ) : 0

 If (  ( DlgS := SubStr( DlgS,1,1 ) ) <> ""  )
  _ := ( DlgS = "F" ) ? NumPut( 0x800000C0 | DlgD, _W$, 44 ) | ( Cap := 0 )
    :  ( DlgS = "N" ) ? NumPut( 0x80000040 | DlgD, _W$, 44 ) | ( Frm := Cap := 0 )
    :  ( DlgS = "B" ) ? NumPut( 0x80800040 | DlgD, _W$, 44 ) | ( Cap := 0 ) | ( Frm := 1 )
    :                   NumPut( 0x80C800C0 | DlgD, _W$, 44 )

 IfNotEqual,DlgB,, SetEnv,_Brush,% DllCall( "CreateSolidBrush", UInt,DlgB )
      
 _hDLG  := DllCall( "CreateDialogIndirectParam", UInt,_hInst, UInt,_DlgT, UInt
,_Owner := ( _Owner <> "" ) ? _Owner : DllCall( "GetShellWindow" ), UInt,_DlgP, UInt,0 )

 VarSetCapacity( _WU, StrLen(_URL) * ( A_IsUnicode ? 1 : 2 ) + 2, 0 )
 A_IsUnicode ? _WU := _URL : DllCall( "MultiByteToWideChar", UInt,0, UInt,0, UInt,&_URL
                                     , Int,-1, UInt,&_WU, Int,StrLen(_URL)+1 )

 _hHTM := DllCall( "GetDlgItem", UInt,_hDLG, UInt,100 )
 DllCall( "atl\AtlAxGetControl", UInt,_hHTM, UIntP,_ppunk )
 DllCall( NumGet( NumGet( _ppunk+0 )+4*0 ), UInt,_ppunk, UInt,_pIWEB, UIntP,_ppwb )
 DllCall( NumGet( NumGet( _ppunk+0 )+4*2 ), UInt,_ppunk ),_pwb := NumGet( _ppwb+0 )
 DllCall( NumGet(_pwb+4*11),UInt,_ppwb, UInt,&_WU, UInt,_pV,UInt,_pV,UInt,_pV,UInt,_pV )
 DllCall( NumGet(_pwb+4*2), UInt,_ppwb )
 
 DllCall( "SetWindowPos", UInt,_hHTM,Int,0,Int,Left,Int,TopM,Int,HtmW,Int,HtmH,UInt,0x14 )
 IfNotEqual,HtmD,0, Control,Disable,,,ahk_id %_hHTM%

 DlgW := Frm + Left + HtmW + Frm + Left,       ClAW := DlgW - Frm - Frm ; ClientArea Width
 DlgH := Frm + Cap + TopM + HtmH + BSpV + BHei + BSpV + Frm
 DlgX := ( DlgX <> "" ) ? DlgX : ( A_ScreenWidth - DlgW ) // 2
 DlgY := ( DlgY <> "" ) ? DlgY : ( A_ScreenHeight - DlgH ) // 2

 StringReplace, Butt,Butt, /,/, UseErrorLevel
 bCount := ErrorLevel+1
 BY := TopM + HtmH + BSpV
 BX := ( Bali=1 ? ( ( ClAW - (BSpH*(bCount-1)) - (BWid*bCount) ) / 2 )
    :  ( Bali=0 ? ( ( BSpH * 2 ) + ( HtmD ? 0 : Left ) )
    :  ( ClAW - (BSpH*(bCount+1)) - (BWid*bCount) - ( HtmD ? 0 : Left ) ) ) )

 Loop, Parse, Butt, /   ;  SetWindowPos flags = SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOZORDER
   DllCall( "SetWindowPos", UInt,BH:=DllCall( "GetDlgItem", UInt,_hDLG, UInt,100+A_Index )
                        , UInt,0, Int,BX, Int,BY, Int,BWid, Int,BHei, UInt,0x40|0x10|0x4 )
 , DllCall( "SetWindowText", UInt,BH, Str,A_LoopField ),   BX := BX + BSpH + BWid
 , _ := ( BNoT<>"" ) ? DllCall( "uxtheme\SetWindowTheme", UInt,BH, UInt,0, UIntP,0 ) : 0
 , _ := ( BSFl<>"" ) ? DllCall( "SetWindowLong", UInt,BH, Int,-16, UInt,0x50018000 ) : 0

 BDef := ( BDef < 1 || BDef > bCount ) ? 1 : BDef ; Force Default Button
 DllCall( "SendMessage", UInt,_hDLG, UInt,0x401, UInt,100+BDef, UInt,0 )    ;  DM_SETDEFID
 
 DllCall( "SetWindowText", UInt,_hDLG, Str,Titl ? Titl : A_ScriptName ) ; Set Dialog Title
 DllCall( "SetWindowPos", UInt,_hDLG, Int,DlgT ? -1 : 1, Int,DlgX, Int,DlgY, Int,DlgW, Int
                        , DlgH, UInt,0x10 )         ; DlgTopmost ? HWND_TOPMOST : HWND_TOP

 While ( nReady <> 4 && DlgW<>"" )  ;  wait until webpage-load adapted from Seans's IE.ahk
   Sleep % 1 + ( DllCall( NumGet(NumGet(1*_ppwb)+224 ), UInt,_ppwb, UIntP,nReady ) >> 32 )
 Sleep, %Slee%

 DllCall( "ShowWindow", UInt,_hDLG, Int,DlgN ? 8 : 5 ) ; DlgNA ? SW_SHOWNA : SW_SHOW
 IfNotEqual,HtmF,0, ControlFocus,, ahk_ID %_hDLG%
 WinWaitClose, ahk_id %_hDLG%,, %Time%
 TimedOut := Errorlevel  ? DllCall( "EndDialog", UInt,_hDLG, UInt,0 ) : 0
 IfNotEqual,AltR,, IfGreater,BDef,0, StringSplit,B,Butt,/
 DllCall( "SetLastError", UInt,TimedOut ? 1 : 0 )
Return AltR ? B%BDef% : BDef
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \
>-  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  O P T I O N S  -  -<
\- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /

Usage: HtmDlg( URL, hwndOwner, Options, OptionsDelimiter )

Parameters :

URL              - A valid URL supported by Internet Explorer including Res:// and File://

hWndOwner        - Handle to the parent window. If invalid handle or 0 ( zero ) is passed,
                   the dialog will have a taskbar button. Passing "" as a parameter will
                   set 'Progman' the owner, thereby supressing the 'Taskbar Button'.

Options          - A series of 'variable overrides' delimited with character specified in
                   'Optionsdelimiter'. Please refer 'VARIABLE OVERRIDES' below.

OptionsDelimiter - The delimiter used in seperating 'variable overrides'


;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;  * * *   V A R I A B L E   O V E R R I D E S   * * *
;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


Important Note: leading 4 characters of a variable will be sufficient.
                for eg.: Instead of 'AltReturn=1' you may use 'AltR=1'


DlgXpos         = X coordinate in pixels, relative to screen
                  Dialog is horizontally centered by default

DlgYpos         = Y coordinate in pixels, relative to screen
                  Dialog is vertically centered by default

DlgTopmost      = 1 will set the Dialog 'Always-on-Top'
                  0 is default

DlgDisable      = 1 will disable the Dialog window
                  No default value

                  Caution:
                  Since there is no way to interact, you may opt to TimeOut the Dialog

DlgStyle        = Frame or NoFrame or Border. Leading character is sufficient, like: F-N-B
                  Default is Caption

                  Note on Styles used:

                  Frame   = WS_POPUP | DS_MODALFRAME
                  NoFrame = WS_POPUP | DS_SETFONT
                  Border  = WS_POPUP | DS_SETFONT | WS_BORDER
                  Caption = WS_POPUP | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU

                  WS_DISABLED is additionally set when DlgDisable=1

DlgNoActivate   = 1 will Show the Dialog without activating it
                  0 is default

DlgBgColor      = ColorRef.  eg: 0x0000FF is Red / Invalid ColorRef will result in Black.

DlgWait         = 1 will delay Dialog from being shown - until HTM is fully loaded
                  
Sleep           = MilliSeconds ( Will be used just before Dialog is shown )
                  Default value is -1, 'No sleep'

Title           = Captionbar Text
                  Default is A_ScriptName

AltReturn       = 1 will return Button-text
                  0 is default and Button-instance will be returned

TimeOut         = Seconds
                  No default value

                  Note: A_LastError will be true when a TimeOut occurs

ClickClose      = 1
                  Default value is 0
                  
                  Note:
                  Mouse L-Click on window's unoccupied clientarea' will close the dialog

                  Tip: Use following to simulate a unobtrusive message ( like TrayTip )
                  DlgTopmost=1, HtmD=1, DlgNA=1, DlgStyle=Border, BHei=0, BSpV=0, Clic=1
                  
LeftMargin      = Spacing in Pixels ( on the left/right sides of WebControl )
                  Default value is 0

TopMargin       = Spacing in Pixels ( above the WebControl )
                  Default value is 0

FonName           ( Not implemented yet )
                  Default is 'MS Shell Dlg' and equivalent

FonSize         = Pointsize ( text size of Button-labels - restricted to 8,10,12,14 )
                  Default value is 8
                  
HtmClientEdge   = 1 to set WS_EX_CLIENTEDGE
                  Default value is 0

HtmDisable      = 1 to disable
                  Default value is 0

HtmWidth        = Width of WebControl in Pixels
                  Default value is 240

HtmHeight       = Height of WebControl in pixels
                  Default value is 140

HtmFocus        = 1 will activate the dialog and WebControl will have input focus
                  Default value is 0

                  Note: DlgNoActivate option will lose effect.
                        For best result, use this option along with DlgWait=1

Buttons         = Button labels seperated with "/"  eg: Buttons=Yes/No/Cancel
                  Default Button is "OK"

BDefault        = Instance of Default Button. eg: To make 3rd Button default, use BDef=3
                  Default forced value is 1

BEscape         = Instance of Button to return when dialog is closed or {Esc} is pressed
                  Default is 0

BWidth          = Button Width in Pixels
                  Default Value is 75

BHeight         = Button Height in Pixels
                  Default value is 23

BSpHorizontal   = Pixels ( affects the spacing on the sides of a button )

BSpVertical     = Pixels ( affects the spacing above/below a button )

BAlign          = 0 or 1 or 2  ( for Left, Center, Right alignment of buttons )
                  Default is 1

BNoTheme        = 1 will remove theme from buttons ( XP & greater )
                  No default value

BSFlat          = 1 will flatten the button by removing the 3D edge - requires BNoTheme=1
                  No default value
                  
;< - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >

*/


braynyac
  • Members
  • 14 posts
  • Last active: Oct 19 2010 08:08 PM
  • Joined: 06 Oct 2010
Thanks for the update majstang. One thing though - I can only get it to work once upon logoff, no matter how I play with the variables (or even remove them). Meaning - if I initiate the script, log off, it blocks log off, but then if I attempt to log off again, it goes right through. Any ideas?

Thanks!

~Braynyac

majstang
  • Members
  • 386 posts
  • Last active: Mar 27 2012 02:12 PM
  • Joined: 29 Aug 2008
Hi Braynyac!

Well, Im no expert, but the script is not built for intercepting Log Off its purpose is to intercept Shutdown or restart. I use it together with a smart shutdownscript (with a bunch of different variables) which is executed every time a recording finish. In that way i can workaround the fact MS removed blocking of standby/hibernation on Vista and forward.

To make it work with Log Off as it does with Shutdown you must rebuild the
WM_QUERYENDSESSION(wParam, lParam) part and make it look similar to the Eventtype = Shutdown lines (Returns false and true) and set a timer. A bit of fiddling around and you should get it to work.

braynyac
  • Members
  • 14 posts
  • Last active: Oct 19 2010 08:08 PM
  • Joined: 06 Oct 2010
Found it!

Here is the entire script. The ini stuff is for the actual logoff script, which checks to see if an application is open, and if it is, continues blocking logoff, but if the application is closed, will allow logoff to continue. I'm currently working to integrate the two scripts. Anyways, my current modification of your script:

;#NoTrayIcon
#Persistent
SetTimer, RunBeforeShutdown, Off
IniWrite, 1, %temp%\logoff.ini, LogOff, TMS_Open
Gui,+LastFound
hwnd:=WinExist()
DllCall("ShutdownBlockReasonCreate","Uint",hwnd,"wStr","TMS is still running, please log off TMS and try again.")
DllCall("kernel32.dll\SetProcessShutdownParameters", UInt, 0x4FF, UInt, 0)
OnMessage(0x11, "WM_QUERYENDSESSION")
Return


WM_QUERYENDSESSION(wParam, lParam)
  {
	IniRead, TMS, %temp%\logoff.ini, LogOff, TMS_Open
	ENDSESSION_Logoff = 0x80000000
    If (lParam & ENDSESSION_Logoff) ; User is logging off.
      EventType = Logoff
    Else     ; System is either shutting down or restarting. and
      EventType = Shutdown
    If (EventType = "Logoff" and TMS = 1)
     {
	   	SetTimer, RunBeforeShutdown, On
		Return false ; Tell the OS to Abort the Shutdown/Logoff.
	 }
	Else If (EventType = "Logoff" and TMS = 0)
		Return true
  }

runBeforeShutdown:
  SetTimer, RunBeforeShutdown, Off
  SendInput, {ENTER}
  Sleep, 1000
  #SingleInstance, Force
  DllCall("ShutdownBlockReasonDestroy","Uint",hwnd)
  MsgBox, 0, Please use the Log Off Icon, Please use the LogOff Icon on your desktop to log off.  Thank you, ITS.
  Reload
Return


!^#r::Reload   ; Reload the script by Alt+Ctrl++Win+R.
!^#x::ExitApp  ; Terminate the script by Alt+Ctrl++Win+X.

It was the addition of the Reload command under the runBeforeShutdown section which allows the script to work no matter how many times you attempt to use the Log Off button.

Now on to integrating the log off script with this one.

Hope this helps,

~Braynyac

majstang
  • Members
  • 386 posts
  • Last active: Mar 27 2012 02:12 PM
  • Joined: 29 Aug 2008
Yes, exactly like that! Nice :D
Good luck!

braynyac
  • Members
  • 14 posts
  • Last active: Oct 19 2010 08:08 PM
  • Joined: 06 Oct 2010
Got it all squared away, two scripts using ini files to check whether the app is open, disable the close button, force log out of the application correctly, disable Alt+F4, and be unobtrusive to the user. Oh, and it works on Windows 7 / Server 2008 R2. Bonus. Here's the code:

Disable_Putty_Close
;========================================================================
; 
; Template:     WinTrigger (former OnOpen/OnClose)
; Description:  Act upon (de)activation/(un)existance of programs/windows
; Online Ref.:  http://www.autohotkey.com/forum/topic43826.html#267338
; * WARNING *   Online version (above) is the old OnOpen/OnClose template!
;
; Last Update:  15/Mar/2010 17:30
;
; Created by:   MasterFocus
;               http://www.autohotkey.net/~MasterFocus/AHK/
;
; Thanks to:    Lexikos, for improving it significantly
;
;========================================================================
;
; This template contains two examples by default. You may remove them.
;
; * HOW TO ADD A PROGRAM to be checked upon (de)activation/(un)existance:
;
; 1. Add a variable named ProgWinTitle# (Configuration Section)
; containing the desired title/ahk_class/ahk_id/ahk_group
;
; 2. Add a variable named WinTrigger# (Configuration Section)
; containing the desired trigger ("Exist" or "Active")
;
; 3. Add labels named LabelTriggerOn# and/or LabelTriggerOff#
; (Custom Labels Section) containing the desired actions
;
; 4. You may also change CheckPeriod value if desired
;
;========================================================================

#Persistent
SetTitleMatchMode 2

; ------ ------ CONFIGURATION SECTION ------ ------

; Program Titles
ProgWinTitle1 = ahk_class PuTTY
WinTrigger1 = Exist


; SetTimer Period
CheckPeriod = 750

; ------ END OF CONFIGURATION SECTION ------ ------

SetTimer, LabelCheckTrigger, %CheckPeriod%
Return

; ------ ------ ------

LabelCheckTrigger:
  While ( ProgWinTitle%A_Index% != "" && WinTrigger := WinTrigger%A_Index% )
    if ( !ProgRunning%A_Index% != !Win%WinTrigger%( ProgWinTitle := ProgWinTitle%A_Index% ) )
      GoSubSafe( "LabelTriggerO" ( (ProgRunning%A_Index% := !ProgRunning%A_Index%) ? "n" : "ff" ) A_Index )
Return

; ------ ------ ------

GoSubSafe(mySub)
{
  if IsLabel(mySub)
    GoSub %mySub%
}

; ------ ------ CUSTOM LABEL SECTION ------ ------

LabelTriggerOn1: 
	IniWrite, 1, %temp%\logoff.ini, LogOff, TMS_Open
	Test:=WinExist(ProgWinTitle1)
	Loop, 10
	{
		DisableCloseButton(Test)
		Sleep, 100
	}
Return
LabelTriggerOff1:
	IniWrite, 0, %temp%\logoff.ini, LogOff, TMS_Open
	Return

; ------ END OF CUSTOM LABEL SECTION ------ ------


DisableCloseButton(hWnd="") {
 If hWnd=
    hWnd:=WinExist("A") 
 hSysMenu:=DllCall("GetSystemMenu","Int",hWnd,"Int",FALSE)
 nCnt:=DllCall("GetMenuItemCount","Int",hSysMenu)
 DllCall("RemoveMenu","Int",hSysMenu,"UInt",nCnt-1,"Uint","0x400")
 DllCall("RemoveMenu","Int",hSysMenu,"UInt",nCnt-2,"Uint","0x400")
 DllCall("DrawMenuBar","Int",hWnd)
Return ""
}
Return

RedrawSysMenu(hWnd="") {
 If hWnd=
    hWnd:=WinExist("A")
 DllCall("GetSystemMenu","Int",hWnd,"Int",TRUE)
 DllCall("DrawMenuBar","Int",hWnd)
Return ""
}

#NoTrayIcon

#IfWinActive ahk_class PuTTY
!F4::Return
#IfWinActive

Prevent_Logoff:
#NoTrayIcon
#Persistent
SetTimer, RunBeforeShutdown, Off

IfWinExist, ahk_class PuTTY
  IniWrite, 1, %temp%\logoff.ini, LogOff, TMS_Open
Else
  IniWrite, 0, %temp%\logoff.ini, LogOff, TMS_Open

Gui,+LastFound
hwnd:=WinExist()
DllCall("ShutdownBlockReasonCreate","Uint",hwnd,"Str","")
DllCall("kernel32.dll\SetProcessShutdownParameters", UInt, 0x4FF, UInt, 0)
OnMessage(0x11, "WM_QUERYENDSESSION")
Return


WM_QUERYENDSESSION(wParam, lParam)
  {
    IniRead, TMS, %temp%\logoff.ini, LogOff, TMS_Open
    ENDSESSION_Logoff = 0x80000000
    If (lParam & ENDSESSION_Logoff) ; User is logging off.
      EventType = Logoff
    Else     ; System is either shutting down or restarting. and
      EventType = Shutdown
    If (EventType = "Logoff" and TMS = 1)
     {
           SetTimer, RunBeforeShutdown, On
        Return false ; Tell the OS to Abort the Shutdown/Logoff.
     }
    Else If (EventType = "Logoff" and TMS = 0)
        IniWrite, 0, %temp%\logoff.ini, LogOff, TMS_Open
        Return true
  }

runBeforeShutdown:
  SetTimer, RunBeforeShutdown, Off
  SendInput, {ENTER}
  Sleep, 1000
  #SingleInstance, Force
  DllCall("ShutdownBlockReasonDestroy","Uint",hwnd)
  WinActivate, ahk_class PuTTY
  MsgBox, 0, PLEASE LOG OFF TMS, TMS is still active.  Please logoff TMS, and try again.  Thank you.
  Reload
Return


I put the ini files in the user's temp dir (%temp%) to make it easy to locate, as this is a Remote Desktop Session host (terminal server). We are using redirected Start menus, so all I had to do was compile these and put a link to them in the startup folder of the users I wished to make sure logged off our TMS application (PuTTY) correctly.

Thank you to everyone who did the majority of the heavy lifting in these scripts (SKAN, Lexikos, MasterFocus, et al).

Hopefully this will help someone else out there! I will be posting a link to this thread from the other thread I posted questions in (http://www.autohotke...p=390398#390398)

Thank you!

~Braynyac