Detect when Windows screen lock/password is active

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
momo2000
Posts: 32
Joined: 25 Jan 2015, 12:00

Detect when Windows screen lock/password is active

04 Jun 2015, 12:21

Can AHK detect when the windows screen has been locked AND unlocked? Password screen lock, I’m talking about. Is there some kind of function? I've searched but don't see anything.

USE CASE: This computer is in a public place, so I need for a tour guide to be able to use the keyboard to unlock the computer, but then after the screen is unlocked, I want to detect that and disable the keyboard. Then the public can only use the mouse to interact. Then when done, the tour guide will hit Windowskey+L and lock the screen again, but I need to detect that so I can make the the keyboard is active again, so that the tour guide can enter the password again (at a later time).
momo2000
Posts: 32
Joined: 25 Jan 2015, 12:00

Re: Detect when Windows screen lock/password is active

04 Jun 2015, 13:50

Well in re-reading my description, I realize there is an error. When the public is done and the tour guide would hit Windowskey+L to lock the computer. . . . they wouldn't be able to if ALL keyboard interaction was blocked, my mistake. SO, there would have to be some way (keyboard keystroke, or mouse click sequence) to simulate a Windowskey+L (or if those keys worked) so the screen lock would work. Thanks.
User avatar
Nextron
Posts: 1391
Joined: 01 Oct 2013, 08:23
Location: Netherlands OS: Win10 AHK: Unicode x32

Re: Detect when Windows screen lock/password is active

04 Jun 2015, 17:14

This locks the workstation: DllCall("LockWorkStation"). You could make it a separate script you can execute by double clicking the mouse, but then you could just as easily create a shortcut to rundll32.exe user32.dll,LockWorkStation to lock the workstation. But you could also make it a mouse button combination, like: XButton2 & XButton1::DllCall("LockWorkStation").

To check is the workstation is locked I use this function, but again you could just use the DllCall:

Code: Select all

WorkstationIsLocked(){
	Return !DllCall("User32\OpenInputDesktop","int",0*0,"int",0*0,"int",0x0001L*1)
}
The downside is you need to repeatedly check if the state changed, so this is better, which is automatically called upon session change:

Code: Select all

WM_WTSSESSION_CHANGE(wParam, lParam, Msg, hWnd){
	static init:=(DllCall( "Wtsapi32.dll\WTSRegisterSessionNotification", UInt, A_ScriptHwnd, UInt, 1) && OnMessage(0x02B1, "WM_WTSSESSION_CHANGE"))
	
	If (wParam=0x6 || wParam=0x7){ ;Logoff or lock
		Run, powercfg -change -monitor-timeout-ac 1,,Hide ;Set monitor standby timeout to 1 minute
		SendMessage,0x112,0xF170,2,,Program Manager ;Monitor Standby
	}Else If (wParam=0x5 || wParam=0x8){ ;Logon or unlock
		Run, powercfg -change -monitor-timeout-ac 20,,Hide ;Set monitor standby timeout to 20 minutes
	}

		
			/*
			wParam::::::
			WTS_CONSOLE_CONNECT := 0x1 ; A session was connected to the console terminal.
			WTS_CONSOLE_DISCONNECT := 0x2 ; A session was disconnected from the console terminal.
			WTS_REMOTE_CONNECT := 0x3 ; A session was connected to the remote terminal.
			WTS_REMOTE_DISCONNECT := 0x4 ; A session was disconnected from the remote terminal.
			WTS_SESSION_LOGON := 0x5 ; A user has logged on to the session.
			WTS_SESSION_LOGOFF := 0x6 ; A user has logged off the session.
			WTS_SESSION_LOCK := 0x7 ; A session has been locked.
			WTS_SESSION_UNLOCK := 0x8 ; A session has been unlocked.
			WTS_SESSION_REMOTE_CONTROL := 0x9 ; A session has changed its remote controlled status. To determine the status, call GetSystemMetrics and check the SM_REMOTECONTROL metric.
			*/
}
I use it to put my monitors in standby and temporarily change to standby timeout to its minimum in the event a disturbance to the mouse wakes them up. You can easily add BlockInputs to those. Do remember the login screen is a special secure desktop with which interaction it not so straight forward. I doubt that blocking the input in the user session also blocks input for the login screen.
sierratango

Re: Detect when Windows screen lock/password is active

28 Nov 2015, 18:58

Does

Code: Select all

DllCall("User32\OpenInputDesktop","int",0*0,"int",0*0,"int",0x0001L*1)
still work for anybody on Windows 10? It doesn't for me. Wondering if anybody knows the updated code to get it to work again.
sierratango

Re: Detect when Windows screen lock/password is active

03 Jan 2016, 01:13

Well after coming back to this and testing it some more with Windows 10 I have concluded that the code does still work but not as well as previous Windows versions. The problem is that the code doesn't apply to the lock screen "curtain shade", only the actual lock screen where you enter your password.
sierratango

Re: Detect when Windows screen lock/password is active

03 Jan 2016, 17:26

This works reliably for me now:

Code: Select all

Sleep, 5000
CoordMode, Pixel, Screen
PixelGetColor, TaskbarColor, 3599, 1049

While (TaskbarColor != 0x151515) {
	Sleep, 3000
	PixelGetColor, TaskbarColor, 3599, 1049
}
Soundbeep,,1000
Msgbox, Unlocked
momo2000
Posts: 32
Joined: 25 Jan 2015, 12:00

Re: Detect when Windows screen lock/password is active

12 Mar 2016, 13:42

sierratango: thanks! appreciate you updating the thread with the W10 working solution.
HIACliff

Re: Detect when Windows screen lock/password is active

17 Mar 2017, 10:27

Nextron's second bit of code was more elegant to begin with, and continues to work on Windows 10.

The workaround of checking the taskbar color doesn't always work, depending on your monitor configuration and Windows theme.
kahbatron

Re: Detect when Windows screen lock/password is active

17 Mar 2017, 17:18

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.

SessionIsLocked()
{
	static WTS_CURRENT_SERVER_HANDLE := 0, WTSSessionInfoEx := 25, WTS_SESSIONSTATE_LOCK := 0x00000000, WTS_SESSIONSTATE_UNLOCK := 0x00000001 ;, WTS_SESSIONSTATE_UNKNOWN := 0xFFFFFFFF
	ret := False

	if (DllCall("ProcessIdToSessionId", "UInt", DllCall("GetCurrentProcessId", "UInt"), "UInt*", sessionId)
	 && DllCall("wtsapi32\WTSQuerySessionInformation", "Ptr", WTS_CURRENT_SERVER_HANDLE, "UInt", sessionId, "UInt", WTSSessionInfoEx, "Ptr*", sesInfo, "Ptr*", BytesReturned)) {
		SessionFlags := NumGet(sesInfo+0, 16, "Int")
		; "Windows Server 2008 R2 and Windows 7: Due to a code defect, the usage of the WTS_SESSIONSTATE_LOCK and WTS_SESSIONSTATE_UNLOCK flags is reversed."
		ret := A_OSVersion != "WIN_7" ? SessionFlags == WTS_SESSIONSTATE_LOCK : SessionFlags == WTS_SESSIONSTATE_UNLOCK
		DllCall("wtsapi32\WTSFreeMemory", "Ptr", sesInfo)
	}

	return ret
}

MsgBox % SessionIsLocked()
User avatar
Don
Posts: 2
Joined: 31 Aug 2014, 14:42

Re: Detect when Windows screen lock/password is active

28 Mar 2018, 17:17

On Win10, I found the same as sierratango with the 'WorkstationIsLocked' function.

The SessionIsLocked function from kahbatron worked the way I expected! thank you! :)
User avatar
danielocdh
Posts: 3
Joined: 01 Jul 2018, 18:42

Re: Detect when Windows screen lock/password is active

01 Jul 2018, 18:48

None of the solutions worked for me on windows 10 1703, maybe it has something to do with me only having remote access via remote desktop connection, disconnecting from the remote desktop connection does lock windows but maybe there is something different done
kkleinfelter
Posts: 32
Joined: 21 Dec 2018, 10:59

Re: Detect when Windows screen lock/password is active

13 Apr 2020, 14:14

This may have changed with (maybe a recent release of) Windows 10. I dunno how consistent it is, but calling

Code: Select all

WinGetTitle,ID,A
returns "Windows Default Lock Screen" into ID for me.
User avatar
geekyadam
Posts: 45
Joined: 01 Aug 2016, 17:11

Re: Detect when Windows screen lock/password is active

27 Jul 2021, 15:08

kkleinfelter wrote:
13 Apr 2020, 14:14
This may have changed with (maybe a recent release of) Windows 10. I dunno how consistent it is, but calling

Code: Select all

WinGetTitle,ID,A
returns "Windows Default Lock Screen" into ID for me.
Just FYI, I just tried running this and immediately locking my laptop (Win+L)...

Code: Select all

Sleep 5000
WinGetTitle,ID,A
msgbox %ID%
...and it returns an empty string. When I try the same code without locking the laptop, it correctly returns the title of the active window. It might not work anymore. Too bad, because I like the simple hacked method to confirm if the screen is locked or not. :/
grosner
Posts: 10
Joined: 11 Sep 2016, 13:08

Re: Detect when Windows screen lock/password is active

28 Jan 2023, 12:56

For me, in Win 11, the above geekyadam solution of returns the value of "Windows Default Lock Screen" after I start this script and then press Win+L. While on the login screen the value is empty.

Code: Select all

#NoEnv
#SingleInstance, Force
#Persistent

SendMode, Input
SetBatchLines, -1
SetWorkingDir, %A_ScriptDir%

setTimer, isLocked, 15000 ; Set Timer fires as soon as script begins executing so therefore, there is a delay in the called function/label/code.

isLocked: 
Sleep, 7000   
setTimer, isLocked, Off
WinGetTitle,ID,A

Switch ID
{
    Case "Windows Default Lock Screen":
       msgbox,0,"Lock Workstation Check", Workstation is locked %ID%, 90
    Case "" : 
       msgbox,0,"Lock Workstation Check", Workstation is on locked and on Login Screen %ID%, 90
    Default:
       msgbox,0,"Lock Workstation Check", Workstation is NOT locked %ID%, 90
       
 }
    
Serge SB
Posts: 1
Joined: 09 Jan 2024, 08:26

Re: Detect when Windows screen lock/password is active

09 Jan 2024, 08:42

I've just registered to post a better (and working for at least Windows 10) solution: (this is a v2 ahk script)

Code: Select all

Loop
{
  Sleep 1000
  if (!WinExist("A")) ; lockscreen password entry
    continue
  if (WinGetProcessName("A") == "LockApp.exe")
    continue

  ; //here goes your code to be executed when the screen is unlocked
}
Note that the WinExist must be called before WinGetProcessName. Otherwise the WinGetProcessName will raise an error when a user enters a password to unlock the screen.

Another note: the use of the WinGetProcessName is a language-independent solution, though may differ for other Windows versions.

Sample code for logging the process name: (place it just before if (WinGetProcessName("A") == "LockApp.exe") line)

Code: Select all

FileAppend WinGetProcessName("A") "`r`n", "c:`\temp`\ahk.txt" ; replace with your preferred filename

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Descolada, Google [Bot], metallizer, Rohwedder and 246 guests