Sign in to follow this  
Followers 0

Keep that RDP session alive

16 posts in this topic

#1 ·  Posted

Happy Friday!

I'm trying to somehow "poll" or something similar RDP sessions that are not currently active (we're talking using the windows mstsc.exe here) so that they do not reach the time limit that knocks them into username/password screen. Thing is, I can't seem to do it :P

Here is what I've tried:

func RDPKeepAlive()
$aActiveServers = winlist("- Remote Desktop")
$hActiveWin = WinGetHandle(WinGetTitle(""))
    For $x = 1 to $aActiveServers[0][0]
        If $hActiveWin <> $aActiveServers[$x][1] Then
            ; do 'em one at a time
            ControlFocus ($aActiveServers[$x][1], "", "ToolbarWindow322")
            $test01 = ControlClick($aActiveServers[$x][1], "", "ToolbarWindow322")

            $test02 = ControlClick($aActiveServers[$x][1], "", "101")

            $test1 = ControlSend($aActiveServers[$x][1], "", "UIMainClass1", "+")

            $test2 = ControlSend($aActiveServers[$x][1], "", "OPWindowClass2", "+")

            $test3 = ControlSend($aActiveServers[$x][1], "", $aActiveServers[$x][0], "+")

            $test4 = ControlSend($aActiveServers[$x][1], "", "", "+")
        EndIf
    Next
endfunc

I've confirmed that all of the above controlclick/send's return a 1, so it's not an issue of the "control" not being found. You'll notice I've been trying to send the shift key to them, i figured that was the least intrusive way to do it... assuming it would freaking work :D

I've inspected ControlSendPlus, but I don't see it offering any more value to what i'm trying here, please correct me if I'm wrong.

Anywho, anyone have ideas on how to do this? My goal is to be able to leave an RDP session in the background or minimized and keep it from timing out to login screen. Putting code on the servers is not an option, and i want them to stay in the background as i often have upwards of 8 to 10 servers i'm switching around in.

thanks!

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Nice idea. I can use i too.

Now I can't test RDP. Did you tried other keys than Shift?

Here is another test:

$test5 = ControlClick($aActiveServers[$x][1], "", "UIMainClass1")

EDIT:

new idea - use some kind of SendMessage to given window handle ...

Edited by Zedna

Share this post


Link to post
Share on other sites

#3 ·  Posted

Nice idea. I can use i too.

Now I can't test RDP. Did you tried other keys than Shift?

Here is another test:

$test5 = ControlClick($aActiveServers[$x][1], "", "UIMainClass1")

EDIT:

new idea - use some kind of SendMessage to given window handle ...

thanks! I'm testing right now (every test takes 10 minutes :P )

I like the SendMessage idea, but i'd have NO idea where to start...

Share this post


Link to post
Share on other sites

#4 ·  Posted

sweet monkey's of madness!

$test5 = ControlClick($aActiveServers[$x][1], "", "OPWindowClass2")

This appears to have worked, so that's pretty awesome. I've got to split but i'll do a bit more testing when i get back.

Share this post


Link to post
Share on other sites

#5 ·  Posted

Cancel that, it works for a little while... and then it freezes the session :P

I'll see what i can figure out...

Share this post


Link to post
Share on other sites

#6 ·  Posted

Cancel that, it works for a little while... and then it freezes the session :P

I'll see what i can figure out...

Show your whole code: How you call RDPKeepAlive().

Share this post


Link to post
Share on other sites

#7 ·  Posted

Well, i've got about 600 lines right now, but I'll show you all the relevant stuff for KeepAlive.

$KeepAliveCount = 0
$RDPWin_KeepAlive = 1
$RDPWin_KATime = 2 *60000

AdlibEnable ( "_OnAdLib", 500 )
Func _OnAdLib()
    $aAdlib = WinList($Win_Match_Title)
    If $RDPWin_KeepAlive = 1 Then
        $KeepAliveCount += 500
        If $KeepAliveCount >= $RDPWin_KATime Then
            _KeepAlive($aAdlib)
            $KeepAliveCount = 0
        EndIf
    EndIf
EndFunc

Func _KeepAlive($aActiveServers)
    $hActiveWin = WinGetHandle(WinGetTitle(""))
    For $x = 1 to $aActiveServers[0][0]
        If $hActiveWin <> $aActiveServers[$x][1] Then
;~                ControlFocus ($aActiveServers[$x][1], "", "ToolbarWindow322")
;~                $test1 = ControlClick($aActiveServers[$x][1], "", "ToolbarWindow322")
;~                $test2 = ControlClick($aActiveServers[$x][1], "", "101")
;~                $test3 = ControlSend($aActiveServers[$x][1], "", $aActiveServers[$x][0], "+")
;~                $test4 = ControlSend($aActiveServers[$x][1], "", "", "+")
;~                $test5 = ControlSend($aActiveServers[$x][0], "", "Input Capture Window", "+")
;~                $test6 = ControlSend($aActiveServers[$x][1], "", "UIMainClass1", "+")
;~                $test7 = ControlSend($aActiveServers[$x][1], "", "OPWindowClass2", "+")
;~                $test8 = ControlClick($aActiveServers[$x][1], "", "OPWindowClass2")
;~                $test9 = ControlClick($aActiveServers[$x][0], "", "Input Capture
                  $test10 = ControlClick($aActiveServers[$x][1], "", "")
        EndIf
    Next    
EndFunc

I haven't tried a ControlFocus combined with thoes last ControlClicks, so maybe I'll do that next. So right now, this function gets called every 2 minutes (AdlibeEnable is not set to 2 minutes because i have 1 or two other functions that run at the 500 ms time).

It appears that the code is actually "working" in that it's doing exactly what it says it is, but for whatever reason, the RDP Session freezes after receiving ControlClick's a few times.

Share this post


Link to post
Share on other sites

#9 ·  Posted

@both

Maybe you can use the RDC Webcomponent and the COM interface to get it going.

RDP COM interface

Just an idea.

regards

ptrex

I suggest you to use autolib from Paul1A, with these library you can control a lot of windows control uncrotolabel with autoit2

Share this post


Link to post
Share on other sites

#10 ·  Posted

I suggest you to use autolib from Paul1A, with these library you can control a lot of windows control uncrotolabel with autoit2

Thanks for the suggestions.

@ptrex - seems to be a bit n/a ? looks like those are for the web connect com objects, and well, i just don't know how to use them :P

@LOULOU - thanks i'll check it out, although at this point i'm not sure if it's an issue of "control" or not. It seems as if I'm really close here, I hope I don't have to dive into that significant library (albeit, excellent) to solve a seemingly small problem :">

Share this post


Link to post
Share on other sites

#11 ·  Posted

Share this post


Link to post
Share on other sites

#12 ·  Posted

Not sure if this will help you or not?

When you login to a RDP session you can set this without a script.

righ-click on desktop - > properties -> screen saver

You will probably see 10 minutes in there, just set it to none.

And you should be done?

Sorry If I missed something :)

John

Share this post


Link to post
Share on other sites

#13 ·  Posted

Not sure if this will help you or not?

When you login to a RDP session you can set this without a script.

righ-click on desktop - > properties -> screen saver

You will probably see 10 minutes in there, just set it to none.

And you should be done?

Sorry If I missed something :)

John

In one regard, you are right in that this type of thing can be set from the server side (it's actually a group policy setting for disconnect time period for inactive sessions, or something like that... not the screensaver timeout).

However, I'm looking for something quicker that doesn't have to be continually configured. I connect on average to about 15 different servers in a single day, and new ones are constantly being added, so going and changing settings each time is a real pain.

Anyway, I'm afraid I may need to let this one die for the time being as thorough testing on my part has not been able to get any of the ControlClick/Send commands to work reliably... and I the webcomponent stuff hasn't really worked yet either.

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

In one regard, you are right in that this type of thing can be set from the server side (it's actually a group policy setting for disconnect time period for inactive sessions, or something like that... not the screensaver timeout).

However, I'm looking for something quicker that doesn't have to be continually configured. I connect on average to about 15 different servers in a single day, and new ones are constantly being added, so going and changing settings each time is a real pain.

Anyway, I'm afraid I may need to let this one die for the time being as thorough testing on my part has not been able to get any of the ControlClick/Send commands to work reliably... and I the webcomponent stuff hasn't really worked yet either.

I got this to work just fine in Perl with Win32::GUITest (which is just a wrapper to the API calls like AutoIT) using the following:

SendMessage($icw, WM_SETFOCUS, undef, undef);

PostMessage($icw, WM_MOUSEMOVE, 0, 0);

$icw is a handle to InputCaptureWindows

WM_SETFOCUS is 0x007

WM_MOUSEMOVE is 0x200

undef is Perl's version of NULL

I'm sure you can use AutoIT to mimic the above code. By the way, the code does NOT steal the focus from your current window. It only informs the window it has focus so that the move mouse command works. Similarly it does not move the mouse, it just tells the TS window that you moved it to position 0, 0.

Good luck,

--man on street

Edited by manonstreet

Share this post


Link to post
Share on other sites

#15 ·  Posted

I got this to work just fine in Perl with Win32::GUITest (which is just a wrapper to the API calls like AutoIT) using the following:

SendMessage($icw, WM_SETFOCUS, undef, undef);

PostMessage($icw, WM_MOUSEMOVE, 0, 0);

$icw is a handle to InputCaptureWindows

WM_SETFOCUS is 0x007

WM_MOUSEMOVE is 0x200

undef is Perl's version of NULL

Thanks for the tip. I just needed to send some mouse movements to specific remote desktop window, so here's the code:

#Include <WinAPI.au3>
#Include <SendMessage.au3>

$WM_SETFOCUS  = 0x007
$WM_MOUSEMOVE = 0x200

If $CmdLine[0] = 0 Then
    MsgBox(0, "Error", "Please enter server name as command line parameter.")
    Exit
Else
    $sName = $CmdLine[1]
Endif

$title = $sName & " - Remote Desktop"

$hWnd = WinGetHandle($title)

If $hWnd = 0 Then
    MsgBox(0, "Error", "Cannot find Remote Desktop Window for server " & $sName)
    Exit
Else
   MsgBox(0, "hWnd", "Sending mouse movements to " & $title & " (" & $hWnd & ")" )
Endif

while 1

   ;MsgBox(0, "sending mouse move to", $hWnd)
    _SendMessage($hWnd, $WM_SETFOCUS)
    _WinAPI_PostMessage($hWnd, $WM_MOUSEMOVE, 0, 0)
    Sleep(60000)

WEnd

Share this post


Link to post
Share on other sites

#16 ·  Posted

Using the help in this forum, I was able to write the following script. It works for me. I have other things I want to add to the script, but this is functional.

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****

#AutoIt3Wrapper_outfile=rdp_keepalive.exe

#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

; Module: rdp_keepalive

;

; Function: Search for RDP sessions and send periodic mouse movements to them to

; to keep them from timing out.

;

; based on original by manonstreet at

;

;

; Usage: See $USAGE string below

;

; Method: Script searches for windows whose title contains " - Remote Desktop" .

; It sends a mouse movement to the windows.

; After all windows have been poked, it sleeps a while and loops.

#Include <WinAPI.au3>

#Include <SendMessage.au3>

#include <GuiEdit.au3>

#include <GUIConstantsEx.au3>

#Include <Date.au3>

;#Include <Hash.au3>

;#include <Debug.au3>

;_DebugSetup ()

;

#include <GetOpt.au3>

AutoItSetOption("MustDeclareVars", 1)

AutoItSetOption ("TrayIconHide", 1) ;# No blinky icon in tray

;#######################################

; Global variables

;#######################################

Const $USAGE = "Usage: rdp_keepalive [-d] [-k]" & @CRLF & _

" -d Debug trace to console (or --debug)" & @CRLF & _

" -k Kill previous execution" & @CRLF & _

" -h Display usage"

Const $SLEEP = 600000 ; sleep loop delay 10 minutes

Const $WM_SETFOCUS = 0x007

Const $WM_MOUSEMOVE = 0x200

Const $PGM = StringRegExpReplace(@ScriptName, "\..*", "") ; Strip extension

Dim $DBG = False ; Global debug flag

; Main Program

Get_Options()

AutoItSetOption("WinTitleMatchMode", 2) ; Match any substring in the title

While 1

Dim $windows = WinList(" - Remote Desktop")

if $windows[0][0] = 0 Then

Dbg("No RDP sessions are active")

EndIf

Dim $i

;Dim $offset = 0

For $i = 1 to $windows[0][0]

Dim $title = $windows[$i][0]

Dim $hWnd = $windows[$i][1]

Dim $restore = False

Dim $hActv

Dim $actTitle

; If window is minimized, can't send mouse clicks to it.

Dim $wstate = WinGetState($hWnd)

If BitAND($wstate, 16) Then

$hActv = WinGetHandle("") ;# Get currently active window handle

$actTitle = WinGetTitle($hActv)

Dbg("Active window is " & $actTitle)

Dbg("Window " & $title & " is minimized, restoring")

WinSetState($hWnd, '', @SW_MAXIMIZE)

WinSetState($hWnd, '', @SW_RESTORE)

$restore = True ; Remember need to restore focus to prev window

EndIf

Dbg("Sending mouse move to " & $title)

_SendMessage($hWnd, $WM_SETFOCUS)

If @error Then Die("_SendMessage error" & @error)

_WinAPI_PostMessage($hWnd, $WM_MOUSEMOVE, 0, 0)

If @error Then Die("_WinAPI_PostMessage error" & @error)

; Restore focus to previously active window

If $restore Then

Dbg("Restoring focus to " & $actTitle)

WinActivate($hActv)

EndIf

Next

;$offset = 0

Sleep($SLEEP)

WEnd

; Should never get here, but just in case

Exit 0

;#######################################

; Function section

;#######################################

Func Get_Options()

Local $aOpts[3][3] = [ _

['-d', '--debug', False], _

['-k', '--kill', False], _

['-h', '--help', False] _

]

_GetOpt_Set($aOpts) ; Set options.

If 0 < $GetOpt_Opts[0] Then ; If there are any options...

While 1 ; ...loop through them one by one.

; Get the next option passing a string with valid options.

Local $sOpt = _GetOpt('dkh')

If Not $sOpt Then ExitLoop ; No options or end of loop.

Switch $sOpt ; What is the current option?

Case '?' ; Unknown options come here. @extended is set to $E_GETOPT_UNKNOWN_OPTION

Usage('Unknown option: ' & $sOpt)

Case 'd'

Logger('Debug mode enabled')

$DBG = True

Case 'k'

Kill_Previous()

Exit 0

Case 'h'

Usage('')

EndSwitch

WEnd

EndIf

EndFunc

;#######################################

; Kill previous execution

;#######################################

Func Kill_Previous()

Local $list = ProcessList() ; List of processes

Local $i, $pname, $pid

Local $found = 0

For $i = 1 to $list[0][0]

Local $pname = $list[$i][0]

Local $pid = $list[$i][1]

; Look for matching process names

If Not StringRegExp($pname, $PGM, 0) Then ContinueLoop

If $pid = @AutoItPID Then ContinueLoop ; Don't commit suicide

$found += 1

Logger("Killing process " & $pid & ", name " & $pname)

If ProcessClose($pid) Then

If ProcessWaitClose($pid, 60) Then

Logger("Process ended")

Else

Logger("Timeout waiting for process to end")

EndIf

Else

Logger("Can't kill process: " & @error)

Endif

Next

If $found = 0 Then

Logger("No " & $PGM & " processes found")

Else

Logger("Killed "& $found & " processes")

EndIf

Sleep(10000) ; Hold window open a while

EndFunc

;#######################################

; Output message if global $DBG flag is set

;#######################################

Func Dbg($msg)

If $DBG Then Logger($msg)

EndFunc

;#######################################

;# Write timestamped message to log window

;#######################################

Func Logger($msg)

Local Static $hLog = 0

Local $ts = @YEAR & "/" & @MON & "/" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC

Local $title = $PGM & " Log"

If $hlog = 0 Then

GUICreate($title, 500, 300)

$hLog = GUICtrlCreateEdit($ts & " Log starting" & @CRLF, 2, 2, 394, 268)

If $hlog = 0 Then

MsgBox(0, $PGM & " Error", "Can't create logging window")

exit 1

EndIf

GUISetState()

EndIf

_GUICtrlEdit_AppendText($hLog, $ts & " " & $msg & @CRLF)

;ConsoleWrite($PGM & " " & $ts & " " & $msg & @CRLF)

EndFunc

;#######################################

;# Log error message and usage string, then Die

;#######################################

Func Usage($msg)

Die($msg & @CRLF & $USAGE)

EndFunc

;#######################################

;# Log message and terminate. Leave window open a while so it can be read.

;#######################################

Func Die($msg)

Logger($msg)

Sleep(15000)

Exit 1

EndFunc

;### E N D ##############################

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