Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.
DeskList=IntControl(84,"",0,0,0) ; Intcontrol returns list of available desktopsand see if the return value can be used to tell is a workstation is locked or not.
I get the exact same output regardless of if the PC is locked or unlocked - "Default Winlogon, ".
Anything else I can try?
But now you got your test script....What does WinGetActive() return.
Did you try looking on Google (and Google Groups) and see if anyone has figured it out for any language. If you can find a sample in any language, then almost always Winbatch can do it too.
Here is apparently some C code. The next step is to get it converted to WinBatch...
int getDesktopType() { HDESK hDesk; char name[200]; DWORD needed; BOOL ret; hDesk=OpenInputDesktop(0,0,0); if(hDesk==NULL) { return 1; // NT is locked } else { ret=GetUserObjectInformation(hDesk,UOI_NAME,name,sizeof(name),&needed); if(ret==TRUE) { name[needed]='\0'; } else { name[0]='\0'; } CloseDesktop(hDesk); if(stricmp(name,"Screen-saver")==0) { return 2; // screen-saver is active } else { return 3; // nothing special } } }
I used my same write-to-a-test-file-and-loop code, and replaced DeskList=IntControl(84,"",0,0,0) with WinGetActive().
WinGetActive() returns Program Manager when the machine is at the desktop (or the window title of the active window), and doesn't return anything (i.e. blank) when the machine is locked.
It's not 100% reliable though, as I am getting blank entries just doing 'stuff' before locking the machine (i.e. opening and closing programs, maximizing and minimizing programs, alt-tabbing between programs,etc).
The only other idea I have to make it more reliable is if WinGetActive() returns a blank, then do a count from 1 to 10 with a 1 minute delay between each count, and compare the WinGetActive()s to make sure they are all blank. If they are all blank I can assume that the machine is locked.
Sound like a good plan, or is there a better way?
#definefunction GetKeyboardState(buf) sDLLName = StrCat(DirWindows(1), "user32.dll") DLLCall(sDLLName, long:"GetKeyboardState", lpbinary:buf) BinaryEodSet(buf, 256) return buf #endfunction #DefineFunction WaitForIdle(time) BoxOpen("Check if System is Idle","Initializing") While @True IntControl(80,0,0,0,0);wait til no keys are pressed statusflag = 0 ;Check mouse currcoordinates = MouseInfo(2) coordinates = currcoordinates ;Check keyboard currbuf = BinaryAlloc(256) newbuf = BinaryAlloc(256) currkbstate = GetKeyboardState(currbuf) kbstate = currkbstate count = 0 While coordinates == currcoordinates && BinaryCompare(currkbstate, 0, kbstate, 0, 256) count = count+1 BoxText(count) if count == time statusflag = 1 break endif timedelay(1); check every second currcoordinates = MouseInfo(2) kbstate = GetKeyboardState(newbuf) EndWhile BinaryFree(currbuf) BinaryFree(newbuf) if statusflag == 1 return 1 endif EndWhile #EndFunction ;timeout = 1800 ; 30 minutes timeout = 10 ; 10 seconds WaitForIdle(timeout) Pause("Workstation",StrCat("Has been Idle for ",timeout," seconds"))
BTW, yes, my code is inefficient spaghetti code with terrible gotos and everything. I am not a professional programmer and it's nowhere near perfect, but my crappy code gets the job done most of the time ;0)
If anyone can help make it more efficient and/or clean up my code, feel free to...
:Check_Time Time=TimeYmdHms ( ) Hour=StrSub(Time, 12, 2) If Hour>="20" || Hour<="04" goto Check_if_Locked Else Delay(1800); 30 minutes Goto Check_Time endif :Check_if_Locked ; This function checks if PC is locked Active_Window=WinGetActive() if Active_Window=="" ; Display(5,"","Workstation is locked") goto Check_if_Inactive else Delay(1800); 30 minutes goto Check_if_Locked endif :Check_if_Inactive ; This function checks for inactivity #definefunction GetKeyboardState(buf) sDLLName = StrCat(DirWindows(1), "user32.dll") DLLCall(sDLLName, long:"GetKeyboardState", lpbinary:buf) BinaryEodSet(buf, 256) return buf #endfunction #DefineFunction WaitForIdle(time) While @True IntControl(80,0,0,0,0);wait til no keys are pressed statusflag = 0 ;Check mouse currcoordinates = MouseInfo(2) coordinates = currcoordinates ;Check keyboard currbuf = BinaryAlloc(256) newbuf = BinaryAlloc(256) currkbstate = GetKeyboardState(currbuf) kbstate = currkbstate count = 0 While coordinates == currcoordinates && BinaryCompare(currkbstate, 0, kbstate, 0, 256) count = count+1 BoxText(count) if count == time statusflag = 1 break endif timedelay(1); check every second currcoordinates = MouseInfo(2) kbstate = GetKeyboardState(newbuf) EndWhile BinaryFree(currbuf) BinaryFree(newbuf) if statusflag == 1 return 1 endif EndWhile #EndFunction timeout = 1800 ; 30 minutes WaitForIdle(timeout) goto Logout_User :Logout_User IntControl(67,0,1,0,0)
; This function checks for inactivity #DefineFunction Getkeyboardstate(buf) ; From 18 30 sdllname = StrCat(DirWindows(1), "user32.dll") DllCall(sdllname, long:"GetKeyboardState", lpbinary:buf) BinaryEodSet(buf, 256) Return buf #EndFunction ; Getkeyboardstate. #DefineFunction Waitforidle(time) ; From 55 While @True Intcontrol(80,0,0,0,0) ; Wait til no keys are pressed. statusflag = 0 ;Check mouse currcoordinates = MouseInfo(2) coordinates = currcoordinates ;Check keyboard currbuf = BinaryAlloc(256) newbuf = BinaryAlloc(256) currkbstate = Getkeyboardstate(currbuf) ; Line 2 kbstate = currkbstate count = 0 While coordinates == currcoordinates && BinaryCompare(currkbstate, 0, kbstate, 0, 256) count = count+1 BoxText(count) If count == time statusflag = 1 Break EndIf ; Count == time. TimeDelay(1) ; Check every second. currcoordinates = MouseInfo(2) kbstate = Getkeyboardstate(newbuf) ; Line 2 EndWhile ; Coordinates == currcoordinates && BinaryCompare(currkbstate, 0, kbstate, 0, 256). BinaryFree(currbuf) BinaryFree(newbuf) If statusflag == 1 Return 1 EndIf ; Statusflag == 1. EndWhile ; @True. #EndFunction ; Waitforidle. ; Start of real code time=TimeYMDHMS ( ) While @True hour=StrSub(time, 12, 2) If hour>="20" || hour<="04" Then Break Delay(1800) ; 30 minutes. EndWhile ; @True. While @True ; This function checks if PC is locked active_window=WinGetActive() If active_window=="" Then Break Delay(1800) ; 30 minutes. EndWhile ; @True. timeout = 1800 ; 30 minutes. Waitforidle(timeout) ; Line 8 Intcontrol(67,0,1,0,0) ; Reboot.
XP Pro, Sp1 (user32.dll 5.1.2600.1255)
2000 Pro, Sp4 (user32.dll 5.0.2195.6897)
NT4, Sp6a (user32.dll 4.0.1381.310)
By Steve Guettler
#definefunction IsMachineLocked() dill = strcat(dirwindows(1),"user32.dll") ;Set the path to the User32.dll lock_state = @false ;Initialize variable (Default return value = @false) dll_hand = dllload(dill) ;Retrieve handle to $dill desktop_hand = dllcall(dll_hand,long:"OpenInputDesktop",word:0,word:0,word:0) ;Retrieve handle of current desktop if desktop_hand < 1 ;If $desktop_hand < 1 (NULL or 0), then machine is locked. lock_state = @true ;Set $lock_state to true if $desktop_hand > 0 endif dllfree(dll_hand) ;Free the DLL handle return(lock_state) ;Return the lock state #endfunctionNote: the success or failure of OpenInputDesktop is going to depend solely on the privileges of the user account calling the function and the effective permissions that exist on the desktop that currently has keyboard & mouse input attached to itself.
Keeping that in mind, in most the situations the method shown above will work provided that the "Winlogon" desktop has not had its security altered to allow the user's process to access it. When the workstation is locked, the "Winlogon" desktop will be the active desktop, and the user's process would normally not have permissions to access it so attempting to open it should fail, with the failure being interpreted as meaning that the workstation is locked.
Using this method in a service may be less reliable, with the reliability depending on whether or not the the service is configured to interact with the desktop.
Article ID: W16457
File Created: 2014:07:18:09:51:38
Last Updated: 2014:07:18:09:51:38