之前写过一篇使用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(,
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/
参考代码:下载