之前寫過一篇使用C# UDP 組播技術做的桌面廣播實現, C# 使用UDP組播實現局域網桌面共享。最終效果差強人意,UDP包在不同的交換機上發送還會出現發送失敗的情況,所以又重新研究了一些新的方法,包括只發送差異畫面的方法,但是依然無法組播。后來搜索到一篇論文,使用RDP技術進行的桌面廣播,實驗了一下,效果出奇的好,是微軟自家的技術,但是必須在Windows 7 及以上版本才能使用,不過,這似乎不再是個問題。
核心機制
1)服務端,開啟一個RDPSession,然后做一個Invitatioon,會產生一個ConnectionString,把這個連接串發送到客戶端
2)客戶端,使用RDPViewer(是一個ActiveX),使用連接字符串連接
沒錯,就這么簡單。
下面以Winform為例
1)創建一個Winform工程作為服務端,添加rdpcomapi 庫的引用;
啟動桌面共享的代碼:
_rdpSession = new RDPSession(); // 新建RDP Session _rdpSession.SetDesktopSharedRect(rect.X, rect.Y, rect.Right, rect.Bottom); // 設置共享區域,如果不設置默認為整個屏幕,當然如果有多個屏幕,還是設置下主屏幕,否則,區域會很大 _rdpSession.Open(); // 打開會話 IRDPSRAPIInvitation invitation = _rdpSession.Invitations.CreateInvitation("baseAuth", "groupName", "", 64); // 創建申請
invitation.ConnectionString 就是可以連接到該會話的連接字符串,不管是用廣播還是其他機制,發送到客戶端即可
客戶端拿到這個連接字符串之后,即可連接到該桌面共享。
2)創建一個Winform程序,在Form上放一個控件,首先在左側的Toolbox面板上右鍵,選擇“Choose Items”,然后選擇 “COM Components”,找到“RDP Viewer Class”,然后確認,再到Form上畫一下
即可創建一個該控件的實例,注意需要將該控件的AccessibleRole改為None,否則調用可能會出錯。
連接代碼:
axRDPViewer1.Connect(args.ConnectionString, Environment.UserName, "");
即可連接到該桌面會話,這樣子就可以看到共享主機的畫面啦,效果可是能達到Windows遠程桌面級別的。
--------------
事件處理:
RDPSession端,可處理的事件有
_rdpSession.OnAttendeeConnected += RdpSessionOnOnAttendeeConnected; // 有加入者連接 _rdpSession.OnAttendeeDisconnected += RdpSessionOnOnAttendeeDisconnected; // 有連接者斷開 _rdpSession.OnControlLevelChangeRequest += RdpSessionOnOnControlLevelChangeRequest; // 連接者控制級別改變,如果只是桌面查看,只需要給 CTRL_LEVEL_VIEW 權限即可
Viewer端,可處理的事件有:
axRDPViewer1.OnConnectionEstablished += AxRdpViewer1OnOnConnectionEstablished; // 建立連接 axRDPViewer1.OnConnectionFailed += AxRdpViewer1OnOnConnectionFailed; // 連接失敗 axRDPViewer1.OnConnectionTerminated += AxRdpViewer1OnOnConnectionTerminated; // 連接中斷 axRDPViewer1.OnError += AxRdpViewer1OnOnError; // 連接錯誤
---------------
另外,這個Session還可以實現遠程控制,這些內容可查看MSDN上的參考來實現。
如果要在WPF工程中使用,首先要創建一個WindowsForm的控件庫,把ActiveX嵌進去,然后包裝一下,再在WPF工程使用使用WindowsFormHost控件來承載該控件即可。
參考文獻:
https://blogs.msdn.microsoft.com/rds/2007/03/23/writing-a-desktop-sharing-application/
參考代碼:下載