1. 程式人生 > >如何關閉遠端桌面後仍處於可互動狀態

如何關閉遠端桌面後仍處於可互動狀態

[轉載自]

  1. http://blog.chenxu.me/post/detail?id=68b1ced9-65b4-4f71-8325-582c70cd996b
  2. http://blog.csdn.net/sogouauto/article/details/43269045
  3. 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’關閉遠端連結。