Jump to content

Recommended Posts

Posted

So due to the pandemic we had to send about 2000 people home to work, some of these people are using RDP to get to the office computer that has licensed software or access that they cant use in our VDI environment.

An issue we have is that many of these computers will go to sleep when left unattended, and we do not want to do a mass change in power policy, so I wanted to just create a one off script for users that they can run on their machine to keep it awake.

I had had a "keep alive" script that I wrote for myself that works perfectly when run locally, but it also keeps the workstation from locking and I can't have that for security reasons.  So I added to this and made sure that it would lock the work station.

The "keep alive" still works when used locally the workstation locks, and never goes to sleep.

However soon as somebody RDP's to the workstation it seems like it stops functioning.

I thought maybe this was because my original script used a mouse movement to keep the computer awake and with RDP the mouse may not exist when you are not active in the session, so I added some key sends as well.  Yet it seems like it still does not work.

I did some creative stuff here to determine if the session is RDP or not as to determine if the workstation should lock, and also I had to get creative about how to send F15 because that was a safe key to send.

 

Here is my current version of my script where I have F15, Mouse and just a left control all happening to ensure that something was happening to keep the computer alive.  What is strange is the script is running, like if the computer goes to sleep or I log into it locally and kick myself out of the RDP session the script is still going, it just seems that it does not work when accessing via RDP, but I can run a script in a RDP session and it works fine the mouse moves, keys send.  I suppose this is some kind of limitation on how Windows intercepts these and so they do not work the same if its not a local session.

 

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Icon=icon_4Mo_icon.ico
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#Include <WinAPI.au3>
#Include <WindowsConstants.au3>
#include <WinAPISys.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#Region ### START Koda GUI section ### Form=
$HCBOCC = GUICreate("HCBOCC", 270, 57, 192, 124)
$Label1 = GUICtrlCreateLabel("Current RDP Status", 0, 0, 264, 24)
GUICtrlSetFont(-1, 12, 800, 0, "MS Sans Serif")
$Label2 = GUICtrlCreateLabel("Lock Status", 2, 22, 264, 24)
GUICtrlSetFont(-1, 12, 800, 0, "MS Sans Serif")
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

GLOBAL $oOBJ = ObjCreate("WScript.Shell")

IsRDP() ;Check Current RDP Status

MsgBox(0, "HCBOCC Automation", "Keeping the RDP Status Window Open or Minimized will keep this computer from going to sleep." & @CRLF & @CRLF & "Closing the Status Window will exit the script and resume normal operation.", 10)

AdlibRegister("_LockMe", 1000*60*5) ;Lock after 5 minutes when RDP is not Active
AdlibRegister("IsRDP", 1000*10) ;Check if RDP Session is running and set GUI Status
AdlibRegister("_KeepAlive", 1000*55) ;Keeps the computer from sleeping
AdlibRegister("_Caffeine", 1000*59) ;Keeps the computer from sleeping

While 1
    Sleep(10)
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

#Region Functions
Func _KeepAlive()
    $aPos = MouseGetPos()
    MouseMove($aPos[0] + 1, $aPos[1], 1)
    MouseMove($aPos[0], $aPos[1], 1)
    Send("{ASC 0x7E}")
    Send("{LCTRL}")
EndFunc

Func _Caffeine()
    $oOBJ.SendKeys('+{F15}')
EndFunc

Func _Lockme()
    If NOT IsRDP() Then ShellExecute("rundll32.exe", 'user32.dll,LockWorkStation')
EndFunc

Func IsRDP() ; Returns True or False
    $iTest = _WinAPI_GetSystemMetrics ($SM_REMOTESESSION)
    If NOT $iTest Then
        GUICtrlSetData($Label1, "RDP Session Not Connected")
        GUICtrlSetData($Label2, "Desktop Will Lock Automatically")
    Else
        GUICtrlSetData($Label1, "RDP Session Connected")
        GUICtrlSetData($Label2, "Desktop Will Not Lock")
    EndIf

    Return $iTest
EndFunc
#EndRegion Functions

Basically just looking for any information on what might be happening, also figured I would share part of the code for sending F15 and Checking RDP session as those both took some research to figure out as we had some older methods posted that no longer seem to work and our standard Send() function only goes to F12 and I am not sure sending the ASC code works properly.

Posted (edited)

No, its not a RDP session limit.  I have tested on my own device.

Just RDP and let it sit overnight to come in in the morning to find my computer asleep.

Wake it up, log in and see the script running!

 

I can only assume that once there is no RDP session in focus that the session does not "receive" mouse or keyboard input from the script, but while you are in the RDP session you will see it working like normal.

 

If you run it locally with no session, it works just fine. 

Edited by ViciousXUSMC
Posted (edited)

so, I understand that is your "home" computer that goes to sleep and not the "office" computer that instead keeps running (right?)
you could try to run a copy of your "keep alive" script on the remote client (the office client) and also another copy on the "home" PC where you are running the RDP software.
Also, when you connect from home to the office computer via RDP, there should not be the need to lock the "office" computer because it results and appears already locked to a person in front of the monitor at the office PC, that is, a person sitting in front of the office PC can't see what you are doing on that computer from home.

Edited by Chimp

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Posted

So how it works is that there is a computer in the office.

It is under power policy to fall asleep.

 

The user can from the office before they go home to work remote or the weekend run this script on the machine in the office,

It should then make sure that workstation gets locked for security reasons, but also keep it from falling asleep so they can remote into it later from home.

 

You can also remote into the machine if it is still awake and run the script remotely, either way should work.

 

It will never be run on the machine that is initiating the RDP session as the user will be able to operate that machine locally.

 

If you run this script locally it works perfectly, but once you establish a RDP session to the machine running the script it seems like it fails to work properly even though its still running and while you are active in a RDP session you can see that it is working.

Posted

can you just make it a simple service to move the mouse around? that way it doesn't need be logged in to work.

My resources are limited. You must ask the right questions

 

  • 2 months later...
Posted

Did anyone every find a solution to the RDP disconnect issue.

I am having a similar issue when I disconnect from a script running on a windows 16 server via RDP, I get unexpected results after the disconnect.

I there anyway to keep the session alive after an RDP disconnect?

Thank you in advance.

Posted

This is my full code dump that I had working.

I tried to use a AutoIT version of Caffine since mouse move and key sends didn't work for me.

The real fix I think was disabling sleep mode.

 

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Icon=icon_4Mo_icon.ico
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#Include <WinAPI.au3>
#include <MsgBoxConstants.au3>
#include <WinAPIProc.au3>
#Include <WindowsConstants.au3>
#include <WinAPISys.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>

Stopwatch(3) ; reset to 0 and starts

#Region ### START Koda GUI section ### Form=
$HCBOCC = GUICreate("HCBOCC", 270, 77, 192, 124)
$Label1 = GUICtrlCreateLabel("Current RDP Status", 2, 0, 264, 24)
GUICtrlSetFont(-1, 12, 800, 0, "MS Sans Serif")
$Label2 = GUICtrlCreateLabel("Lock Status", 2, 24, 264, 24)
GUICtrlSetFont(-1, 12, 800, 0, "MS Sans Serif")
$LapsedTime = GUICtrlCreateLabel("In 10 Minutes   00:00:00.0", 4, 47, 300, 25)
GUICtrlSetFont(-1, 12, 800, 0, "MS Sans Serif")
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

GLOBAL $oOBJ = ObjCreate("WScript.Shell")
Local $aRet = DllCall("kernel32.dll", "long", "SetThreadExecutionState", "long", 0x80000003) ;0x80000003 to disable windows sleep mode

IsRDP() ;Check Current RDP Status

MsgBox(0, "HCBOCC Automation", "Keeping the RDP Status Window Open or Minimized will keep this computer from going to sleep." & @CRLF & @CRLF & "Closing the Status Window will exit the script and resume normal operation.", 10)

AdlibRegister("_LockMe", 1000*60*10) ;Lock after 10 minutes when RDP is not Active
AdlibRegister("IsRDP", 1000*10) ;Check if RDP Session is running and set GUI Status
AdlibRegister("_KeepAlive", 1000*55) ;Keeps the computer from sleeping
AdlibRegister("_Caffeine", 1000*59) ;Keeps the computer from sleeping

While 1
    ;Sleep(2)
    $aMouseCord1 = MouseGetPos()
    $x = Int(Stopwatch() / 100)
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Local $aRet = DllCall('kernel32.dll', 'long', 'SetThreadExecutionState', 'long', 0x80000000)    ;Remove the always on so it will go to sleep
            Exit
    EndSwitch
    If $x <> Int(Stopwatch() / 100) Then
        $totsec = Int(Stopwatch() / 1000) ; ms to sec
        $hr = Int($totsec / 3600) ; hours
        $mn = Int(($totsec - ($hr * 3600)) / 60) ; minutes
        $sc = Int(($totsec - ($hr * 3600) - ($mn * 60))) ; seconds
        $tn = Int((Int(Stopwatch() / 100) - ($hr * 36000) - ($mn * 600) - ($sc * 10))) ; tenths of a second
        GUICtrlSetData($LapsedTime, "In 10 Minutes   " & StringFormat("%02s", $hr) & ":" & StringFormat("%02s", $mn) & ":" & StringFormat("%02s", $sc) & "." & StringFormat("%01s", $tn))
    EndIf
    $aMouseCord2 = MouseGetPos()
    If $aMouseCord1[0] <> $aMouseCord2[0] Then Renew()
WEnd

#Region Functions
Func _KeepAlive()
    $aPos = MouseGetPos()
    MouseMove($aPos[0] + 1, $aPos[1], 1)
    MouseMove($aPos[0], $aPos[1], 1)
    ;Send("{ASC 0x7E}")
    ;Send("{LCTRL}")
EndFunc

Func _Caffeine()
    $oOBJ.SendKeys('+{F15}')
EndFunc

Func _Lockme()
    If NOT IsRDP() Then ShellExecute("rundll32.exe", 'user32.dll,LockWorkStation')
EndFunc

Func IsRDP() ; Returns True or False
    $iTest = _WinAPI_GetSystemMetrics ($SM_REMOTESESSION)
    If NOT $iTest Then
        GUICtrlSetData($Label1, "RDP Session Not Connected")
        GUICtrlSetData($Label2, "Desktop Will Lock Automatically @ 10 Minutes")
        GUICtrlSetState($LapsedTime, $GUI_SHOW)
    Else
        GUICtrlSetData($Label1, "RDP Session Connected")
        GUICtrlSetData($Label2, "Desktop Will Not Lock")
        GUICtrlSetState($LapsedTime, $GUI_HIDE)
    EndIf

    Return $iTest
EndFunc


Func _Example()
    ; disable ScreenSaver and other windows sleep features
    _WinAPI_SetThreadExecutionState(BitOR($ES_DISPLAY_REQUIRED, $ES_CONTINUOUS, $ES_SYSTEM_REQUIRED, $ES_AWAYMODE_REQUIRED))
    MsgBox($MB_OK, 'Testing', 'Close this tester window when you be sure that your ScreeSaver not runing.')

    ; back to normal windows behavior
    _WinAPI_SetThreadExecutionState($ES_CONTINUOUS)
EndFunc   ;==>_Example


Func Renew()
    Stopwatch(3)
    AdlibRegister("_LockMe", 1000*60*10)
EndFunc ;End Renew

Func AutoLogoff()
    Run(@ComSpec & " /c shutdown -L")
EndFunc ;End AutoLogoff

Func Stopwatch($ToggleTo = 4)
    Static Local $Paused = True
    Static Local $Stopwatch = 0
    Static Local $TotalTime = 0
    Switch $ToggleTo
        Case 0 ; pause counter
            If $Paused Then
                SetExtended($Paused) ; $Paused status
                Return $TotalTime ; already paused, just return current $TotalTime
            Else
                $TotalTime += TimerDiff($Stopwatch)
                $Paused = True
                SetExtended($Paused)
                Return $TotalTime
            EndIf
        Case 1 ; unpause counter
            If $Paused Then
                $Stopwatch = TimerInit()
                $Paused = False
                SetExtended($Paused)
                Return $TotalTime
            Else
                SetExtended($Paused)
                Return $TotalTime + TimerDiff($Stopwatch)
            EndIf
        Case 2 ; reset to 0 and pause
            $Paused = True
            $TotalTime = 0
            SetExtended($Paused)
            Return $TotalTime
        Case 3 ; reset to 0 and restart
            $Paused = False
            $TotalTime = 0
            $Stopwatch = TimerInit()
            SetExtended($Paused)
            Return $TotalTime
        Case 4 ; return status
            SetExtended($Paused)
            If $Paused Then
                Return $TotalTime
            Else
                Return $TotalTime + TimerDiff($Stopwatch)
            EndIf
    EndSwitch
EndFunc   ;==>Stopwatch

#EndRegion Functions

 

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
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...