【问题标题】:Keep alive code fails with new RDP client新的 RDP 客户端保持活动代码失败
【发布时间】:2012-11-27 16:31:58
【问题描述】:

对于我们的安全终端服务器项目,我们需要保持 RDP 会话打开,即防止远程计算机超时并锁定会话。一点背景:

我们有几个配置为中间代理的虚拟服务器,其中一个客户端向虚拟服务器启动 RDP 会话,并在那里启动应用程序。该应用程序从数据库中读取连接数据,包括用于连接到最终目标计算机的用户名和密码。

对于远程桌面会话,我们使用从 MSTSCAX.DLL 中提取的 ActiveX 控件(使用 AxImp)。因为用户无权访问远程机器的密码,我们绝对必须防止会话超时。

在过去的几个月里,我们一直在使用由 Timer 对象触发的以下代码来完成此操作。效果很好,直到我不得不将 RDP 客户端升级到版本 6 才能访问 Server 2008 机器(我们使用的是版本 4 或 5,不确定是哪个)。从那时起,对 SendKeys 的调用有时会引发 HRESULT E_FAIL 错误——通常足以导致重大问题。

有没有人知道可能是什么原因造成的?更好的是,有没有人有更好的方法来实现这一点,可以与较新的 RDP 客户端一起使用?

谢谢, 戴夫

        _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 );
        }
    }

【问题讨论】:

  • 只是想知道。为什么不使用某种代理服务器来直接连接到数据库?
  • 我不确定你想说什么。你会用代理服务器代替什么?您是在尝试重新设计系统,还是解决超时问题?
  • 作为后续,我们在此期间所做的只是忽略异常。这样做的缺点是会话有时会超时。好处是,我们的代表不必处理消息框。到目前为止,这比预期的要好,因为超时的发生率相对较低。不过,我们仍然需要更好的解决方案……

标签: c# .net-3.5 activex terminal-services keep-alive


【解决方案1】:

有没有办法通过某种 mousemove 来代替 sendkeys?如果您只将鼠标移动几个像素,我怀疑这将不那么具有侵入性。不过,我不确定 RDP 是否有某种鼠标移动阈值 - 也许几个像素不足以重置断开/锁定超时。

我们最终会遇到同样的问题(我们的终端服务器目前是 2003,但我们会在某个时候升级到 2008),所以我真的很想知道您的解决方案最终是什么。

【讨论】:

    【解决方案2】:

    我同样需要从客户端保持 RDP 6 处于活动状态。通过谷歌来到这里,尝试了sendkey和mousemove,没有用。原来WM_ACTIVATE 成功了。

    这是我的基本AutoHotkey 脚本片段:

    SetTimer, RemoteMachine_Tick, 60000
    

    RemoteMachine_Tick:

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

    【讨论】:

    • 这是什么语言? "SendMessage, 0x006, 1, 0, , remote01 - Remote Desktop;" 是什么意思?意思是,“WM_ACTIVATE(0x006) WA_ACTIVE(1)”?
    • 这是一个AutoHotkey脚本,WM_ACTIVATE是一个消息,WA_ACTIVE是一个消息参数。在幕后,它们只是数字——WM_ACTIVATE 是 6,WA_ACTIVE 是 1。msdn link
    【解决方案3】:

    您是否尝试过管理 Group Policies 来配置终端服务并保持会话处于活动状态?

    【讨论】:

    • 如果我能说服我们所有 1400 多个客户的 IT 部门这样做,那将是一个好主意。由于这不是真的可行(甚至是不可取的),我仍然需要一个客户端解决方案。
    • 所以客户端启动到虚拟服务器的 RDP 会话并托管虚拟服务器?我的印象是您托管了 RDP 进入的服务器。
    • 其实你是对的。我们确实管理第一级虚拟服务器,并且我们确实使用组策略防止会话超时。连接的下一段是我所关心的,当我们从那里 RDP 到客户端计算机时。
    猜你喜欢
    • 1970-01-01
    • 2021-11-10
    • 1970-01-01
    • 2016-06-17
    • 2020-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多