如何关闭远程桌面后仍处于可交互状态
如何关闭远程桌面后仍处于可交互状态
标签(空格分隔): windows 服务器 远程桌面 模拟鼠标
[转载自]
- http://blog.chenxu.me/post/detail?id=68b1ced9-65b4-4f71-8325-582c70cd996b
- http://blog.csdn.net/sogouauto/article/details/43269045
- http://ju.outofmemory.cn/entry/181730
默认情况下,当用户没有在 Windows 上执行任何输入(没有鼠标键盘等的输入)并保持一定时间后,Windows 会自动切换到锁屏模式(或屏保模式),甚至待机。
一般情况下,这样不会有任何问题,而且也是推荐的设置(出于安全和节能的角度)。但是,如果这台电脑被用于进行一些自动化的测试,尤其是涉及到 UI 的交互操作时(比如,测试过程中用脚本操控鼠标来模拟点击一个按钮),这将会是个很大的问题:鼠标键盘失效了!UI 自动化做不下去了!
解决这个办法的方案很简单:设置 Windows 的电源模式,让 Windows 不要自动锁屏和待机,同时去掉屏保。
问题进阶
UI 自动化测试期间,执行测试的电脑几乎不能继续被他人使用(因为鼠标、键盘等输入设备此时需要响应自动化测试脚本)。为了不影响电脑使用,一般会搭一个虚拟机,然后远程连接到虚拟机里,在虚拟机里执行 UI 自动化测试。
但是,万一你不小心把某个远程桌面“最小化”了...Oops,你的自动化测试就挂了。既然连最小化都会失败,相信你已经猜到直接关闭远程桌面的后果了。
为什么最小化或关闭远程连接的桌面会导致自动化测试失败呢?
概念介绍
要解释清楚这个原因,首先必须要了解3个在Windows 操作系统中的经常用到,却很陌生的对象:Session、Windows Station 和 Desktop。
Session
用户会话,每个登录操作系统的用户都会分配一个唯一的登录会话,用于标识该用户。操作系统(Vista 及以上)保留0号会话给一些系统服务及用户态的驱动使用,第1个登录系统的用户使用的 Session ID 为1,该用户执行的所有应用程序都在 Session 1 下执行。
我们可以打开任务管理器,切换到进程列表,然后在菜单->视图->选择列中,勾选 Session ID 列。
如果有其它的用户登录到系统,就会看到 Session ID 大于1的情况,比如远程桌面。
Windows Station
Station 可以理解为工作站,它被认为是桌面和进程的安全边界。因此,每一个 session 都会包含多个 station,而每一个 Station 又包含1个或多个 Desktop。
但是,多个 Station 中,只有名字叫 Winsta0 的 Station 才是交互式的 station,也就是说只有它才能有 UI 并接受用户输入。所以每个 Session 都有一个叫 Winsta0 的用户进行交互。
Desktop
这里的 Desktop 并不是我们进入系统后所看到的那个蓝底的桌面(,我们看到的这个桌面,实际上只是一个窗口)。而是逻辑上的一个显示对象,它包含可显示的 GUI 对象(比如窗口、菜单、钩子等)。一般情况下,WinSta0 包含至少三个Desktop:登录(WinLogon)、屏保(ScreenSaver)和默认(Default,能看到所有应用程序的地方)。
同一时刻只能有一个Desktop处于激活状态(而能激活的 Desktop 只能属于 Winsta0)。用户还没登录的时候,登录桌面处于激活状态。登录之后,默认的Desktop处于激活状态。当达到系统电源设置的某个点的时候,系统切换到屏保,此时屏保Desktop处于激活状态。当用户按下 Ctrl + Alt + Delete 时,切换到登录Desktop,此时登录Desktop处于激活状态。
激活状态的Desktop才能接收用户输入,钩子才能获取其中的某个窗口消息。
如果你已经体验过 Win10,那应该就会知道 Win10 提供了很方便的创建多个Desktop的方式。
关于上述三个对象更多的解释,请大家查看下面的参考链接。
Desktop
Window Stations
Why do UI macros fail when I disconnect or minimize the Remote Desktop/Terminal Services session?
Running Tests via Remote Desktop - Overview
Keep an Active Session Running on the Execution Server
原 因
了解了上述三个对象后,就可以比较容易的解释出现问题的原因了。
最小化
最小化会让远程桌面的会话切换到无图形界面的模式,这自然就无法继续接收鼠标、键盘的指令了。
关闭远程桌面
关闭远程桌面会让系统切换到登录Desktop的界面,而在该Desktop上并没有我们打开的其它窗口,因此会导致 UI 自动化测试失败。
解决办法
最小化 (注意,正在测试...并未成功,有另一篇文章提到修改方法应为 从机器A通过远程桌面连接机器B,则需要在机器A上修改注册表)
通过设置注册表的值可以阻止切换到无图形界面。
32位系统
找到 HKEY_LOCAL_MACHINE\Software\Microsoft\Terminal Server Client,创建一个 DWORD 类型的值,名字叫做 RemoteDesktop_SuppressWhenMinimized,然后设置值为 2。
64位系统
找到 HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Terminal Server Client,然后和 32 位一样创建一个DWORD 类型的值,名字叫做 RemoteDesktop_SuppressWhenMinimized,并设置值为 2。
上面的改动会应用于整个机器,如果只想应用于当前的用户,把 LOCAL 替换成 USER。
关闭远程桌面
方案一:
在远程桌面(被连接到的电脑)中先执行 query session 来查看当前登录到的 session,(远程桌面的 sessionName 都以 rdp-tcp 开头)。
然后用管理员用户打开命令行工具,并执行 'tscon rdp-tcp#0 /dest:console',其中 rdp-tcp#0 为该该命令会关闭远程桌面的连接,然后把连接返回给远程的那台电脑(绕开登录过程)。这里的 console 只是一个 session 的名字,而这个名字的意思并非是 C# 中 “控制台” 的意思,而是指带有输入输出设备的机器,一般直接登录电脑的会话就是 console。
假设电脑A执行 mstsc 连接到电脑B(,连接成功后,电脑B黑屏),此时在电脑B上执行上述命令后(替换对应的session名字),电脑A中的远程连接窗口会被关闭,并提示远程连接会话已经终止。电脑B(假设运行在另一台物理机上)会恢复到已经登录的状态,如果需要重新让电脑B恢复锁屏状态,可以在电脑B上执行如下命令:
rundll32.exe user32.dll,LockWorkStation
方案二:
假设用于跑 UI 自动化的机器是虚拟机A,现在再使用另一台虚拟机B作为中转。本机先连接到虚拟机B,然后再从虚拟机B连接到虚拟机A,最后断开虚拟机B。
方案三:(引自 UI自动化中关闭远程桌面连接,鼠标键盘失效的解决方案)
远程桌面mstsc远程登录虚拟机时,在虚拟机中新建文本文档,写入内容
@%windir%\System32\tscon.exe 0 /dest:console
@%windir%\System32\tscon.exe 1 /dest:console
@%windir%\System32\tscon.exe 2 /dest:console
将文本文档重新命名为‘Close_RDP’,并将后缀名改为‘.bat’,双击文件‘Close_RDP.bat’关闭远程链接。
方案四:(引自 [UI测试]远程桌面连接的困扰)
并没有找到例子,有时间我会写上例子。
使用C#开源远程桌面连接软件Multi RDP Client .NET,当远程连接上后,最小化的情况下,鼠标键盘模拟仍然是生效的。另外由于是开源软件,所以我们可以在源码基础上,扩展自己的功能,比如说在自动化测试过程中,接收请求,自动远程连接相应机器,来满足自动化测试的需求。另外,使用第三方远程连接软件,我们可以将软件的数据保存到远程的数据库中,这样,我们只需要有软件,不需要知道机器密码就可以使用执行机器了。