3
votes

For our Secure Terminal Server project, we have a need to keep the RDP session open, that is, to prevent the remote computer from timing out and locking the session. A little background:

We have several virtual servers configured as go-between agents, with a client piece that launches a RDP session to the virtual servers, and starts an application there. That application reads connection data from a database, including the username and password for connecting on to the final destination computer.

For remote desktop sessions, we use the ActiveX control extracted from MSTSCAX.DLL (using AxImp). Because the user does not have access to the password for the remote machine, we absolutely must keep the session from timing out.

For the past several months, we have been using the following code, triggered by a Timer object, to accomplish this. That worked great, until I had to upgrade the RDP client to version 6 in order to access Server 2008 boxes (we were using version 4 or 5, not sure which). Since then, the call to SendKeys will sometimes throw an HRESULT E_FAIL error -- often enough to cause major problems.

Does anyone have an idea as to what may be causing this? Better yet, does anyone have a better way to accomplish this that may work with the newer RDP client?

Thanks, Dave

        _mstscKeyControl = (IMsRdpClientNonScriptable)_mstsc.GetOcx();

    private void KeepAlive()
    {
        try
        {
            if ( null != _mstsc && 0 != _mstsc.Connected )
            {
                bool[] bKeyUp = new bool[ 20 ];
                int[] KeyData = new int[ 20 ];            // value matches lParam parameter of WM_DOWN message

                /*
                 * Send CAPS LOCK on followed by OFF 
                 * 
                 * The SendKeys routine will not allow remote data in a single call to be mixed with
                 * local data so this shouldn't mess up anything.
                 */

                KeyData[ 0 ] = (int)MapVirtualKey( 14, 0 );    // vk_capital = CAPS LOCK
                bKeyUp[ 0 ] = false;
                KeyData[ 1 ] = KeyData[ 0 ];
                bKeyUp[ 1 ] = true;

                _mstscKeyControl.SendKeys( 2, ref bKeyUp[ 0 ], ref KeyData[ 0 ] );
            }
        }
        catch ( Exception ex )
        {
            MessageBox.Show( ex.Message + Environment.NewLine + ex.StackTrace );
        }
    }
3
just wondering. why not use some kind of proxy server instead so that you can connect to the database directly?djangofan
I'm not sure what you're trying to say. What would you replace with the proxy server? Are you trying to redesign the system, or solve the timeout problem?DaveN59
As a follow-up, what we are doing in the interim is simply to ignore the exception. The downside of this is the session will sometimes time out. The upside is, our reps don't have to deal with the message box. So far, this is working better than expected, as the incidence of timeouts is relatively low. We still need a better solution, though...DaveN59

3 Answers

1
votes

Instead of a sendkeys, is there a way to pass some kind of mousemove instead? I suspect this would be less invasive, if you only move the mouse a few pixels. I'm not sure if RDP has some kind of mouse movement threshold, though - maybe a few pixels isn't enough for it to reset the disconnect/lock timeout.

We'll eventually have this same problem (our terminal server is currently 2003, but we'll upgrade to 2008 at some point), so I'd really be interested to know what your solution ends up being.

1
votes

I have the same need to keep RDP 6 alive from the client side. Came here via google, tried sendkey and mousemove, didn't work. Turn out WM_ACTIVATE do the trick.

Here's my basic AutoHotkey script segment:

SetTimer, RemoteMachine_Tick, 60000

RemoteMachine_Tick:

IfWinNotActive, remote01 - Remote Desktop 
    SendMessage, 0x006, 1, 0, , remote01 - Remote Desktop; 
    WM_ACTIVATE(0x006)  WA_ACTIVE(1)
return
0
votes

Have you tried managing Group Policies to configure Terminal Services and keep the session active?