# 如何关闭远程桌面后仍处于可交互状态 - 班哥静听 - 博客园

By [区块链学习](https://paragraph.com/@whitelistee) · 2022-02-13

---

如何关闭远程桌面后仍处于可交互状态
-----------------

标签（空格分隔）： windows 服务器 远程桌面 模拟鼠标  
\[转载自\]

1.  [http://blog.chenxu.me/post/detail?id=68b1ced9-65b4-4f71-8325-582c70cd996b](http://blog.chenxu.me/post/detail?id=68b1ced9-65b4-4f71-8325-582c70cd996b)
    
2.  [http://blog.csdn.net/sogouauto/article/details/43269045](http://blog.csdn.net/sogouauto/article/details/43269045)
    
3.  [http://ju.outofmemory.cn/entry/181730](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](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682573%28v=vs.85%29.aspx)  
[Window Stations](https://msdn.microsoft.com/en-us/library/windows/desktop/ms687096%28v=vs.85%29.aspx)  
[Why do UI macros fail when I disconnect or minimize the Remote Desktop/Terminal Services session?](http://help.mjtnet.com/article/30-why-do-ui-macros-fail-when-i-disconnect-or-minimize-the-remote-desktop-terminal-services-session)  
[Running Tests via Remote Desktop - Overview](https://support.smartbear.com/viewarticle/69891/)  
[Keep an Active Session Running on the Execution Server](http://docs.telerik.com/teststudio/knowledge-base/scheduling-kb/keep-active-session)

原 因
---

  了解了上述三个对象后，就可以比较容易的解释出现问题的原因了。

最小化  
  最小化会让远程桌面的会话切换到无图形界面的模式，这自然就无法继续接收鼠标、键盘的指令了。

关闭远程桌面  
  关闭远程桌面会让系统切换到登录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自动化中关闭远程桌面连接，鼠标键盘失效的解决方案](http://blog.csdn.net/sogouauto/article/details/43269045))

  远程桌面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测试\]远程桌面连接的困扰](http://ju.outofmemory.cn/entry/181730))

  并没有找到例子，有时间我会写上例子。  
  使用C#开源远程桌面连接软件Multi RDP Client .NET，当远程连接上后，最小化的情况下，鼠标键盘模拟仍然是生效的。另外由于是开源软件，所以我们可以在源码基础上，扩展自己的功能，比如说在自动化测试过程中，接收请求，自动远程连接相应机器，来满足自动化测试的需求。另外，使用第三方远程连接软件，我们可以将软件的数据保存到远程的数据库中，这样，我们只需要有软件，不需要知道机器密码就可以使用执行机器了。

---

*Originally published on [区块链学习](https://paragraph.com/@whitelistee/kw745zQ3Tb41AbrKkH8c)*
