最小化及關閉遠程桌面後鍵盤與鼠標仍處於可交互狀態

        默認情況下,當用戶沒有在 Windows 上執行任何輸入(沒有鼠標鍵盤等的輸入)並保持一定時間後,Windows 會自動切換到鎖屏模式(或屏保模式),甚至待機。
       一般情況下,這樣不會有任何問題,而且也是推薦的設置(出於安全和節能的角度)。但是,如果這臺電腦被用於進行一些自動化的測試,尤其是涉及到 UI 的交互操作時(比如,測試過程中用腳本操控鼠標來模擬點擊一個按鈕),這將會是個很大的問題:鼠標鍵盤失效了!UI 自動化做不下去了!
解決這個辦法的方案很簡單:設置 Windows 的電源模式,讓 Windows 不要自動鎖屏和待機,同時去掉屏保。

問題進階

  腳本自動化測試期間,執行測試的電腦幾乎不能繼續被他人使用(因爲鼠標、鍵盤等輸入設備此時需要響應自動化測試腳本)。爲了不影響電腦使用,一般會搭一個虛擬機,然後遠程連接到虛擬機裏,在虛擬機裏執行 腳本自動化測試。
  但是,萬一你不小心把某個遠程桌面“最小化”了...GAME OVER,你的自動化測試就掛了。既然連最小化都會失敗,相信你已經猜到直接關閉遠程桌面的後果了。
  爲什麼最小化或關閉遠程連接的桌面會導致自動化測試失敗呢?

概念介紹

  要解釋清楚這個原因,首先必須要了解3個在Windows 操作系統中的經常用到,卻很陌生的對象:Session、Windows Station 和 Desktop。

Session

  用戶會話,每個登錄操作系統的用戶都會分配一個唯一的登錄會話,用於標識該用戶。操作系統(2008 及以上)保留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的界面,而在該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 的名字,而這個名字的意思並非是  “控制檯” 的意思,而是指帶有輸入輸出設備的機器,一般直接登錄電腦的會話就是 console。
  假設電腦A執行 mstsc 連接到電腦B(連接成功後,電腦B黑屏),此時在電腦B上執行上述命令後(替換對應的session名字),電腦A中的遠程連接窗口會被關閉,並提示遠程連接會話已經終止。電腦B(假設運行在另一臺物理機上)會恢復到已經登錄的狀態,如果需要重新讓電腦B恢復鎖屏狀態,可以在電腦B上執行如下命令:

rundll32.exe user32.dll,LockWorkStation

方案二:
  假設用於跑自動化的機器是虛擬機B,現在再使用另一臺虛擬機A作爲中轉。本機先連接到虛擬機A,然後再從虛擬機A連接到虛擬機C,最後斷開虛擬機A。
此處輸入圖片的描述

方案三:

  先通過方案一查詢console是哪個會話ID,上圖所示爲3

遠程桌面mstsc遠程登錄虛擬機時,在虛擬機中新建文本文檔,寫入內容

@%windir%\System32\tscon.exe 0 /dest:console
@%windir%\System32\tscon.exe 1 /dest:console
@%windir%\System32\tscon.exe 2 /dest:console
@%windir%\System32\tscon.exe 3 /dest:console

將文本文檔重新命名爲‘Close_RDP’,並將後綴名改爲‘.bat’,雙擊文件‘Close_RDP.bat’關閉遠程鏈接。不過此方法存在不太穩定的情況,不推薦使用。經測試主要問題是出現在tscon.exe有的系統可以成功運行,有的會運行失敗。得多找幾個不同系統的tscon.exe測試保證成功。

方案四:經研究這個方法最可靠(後期代碼實現在上傳)

使用C#開源遠程桌面連接軟件Multi RDP Client .NET,當遠程連接上後,最小化的情況下,鼠標鍵盤模擬仍然是生效的。另外由於是開源軟件,所以我們可以在源碼基礎上,擴展自己的功能,比如說在自動化測試過程中,接收請求,自動遠程連接相應機器,來滿足自動化測試的需求。另外,使用第三方遠程連接軟件,我們可以將軟件的數據保存到遠程的數據庫中,這樣,我們只需要有軟件,不需要知道機器密碼就可以使用執行機器了。

總結

        以上幾種解決遠程桌面問題的方法,在工作中都有可能用到,比如說在腳本初期,我們使用到的機器不是太多的情況下,腳本的運行需要手工進行,這時,我們可以採用註冊表法,這樣就可以將遠程桌面的窗口最小化到任務欄了;而當我們機器不斷增多時,比如說自動化執行的機器超過了10個甚至更多,這時我們最好藉助開源遠程連接軟件了。對於大規模的虛機管理,推薦使用開源遠程連接軟件來進行管理。

參考:https://www.cnblogs.com/bangejingting/p/6846480.html

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章