☰
VS2019远程桌面源码实战:从直接运行到踩坑修复
2026/10/31 17:02:16 网站建设 项目流程

简介:面向C#开发者的远程桌面应用源码,采用Visual Studio 2019构建,包含OriginalServer服务端与OriginalClient客户端两个完整工程,可直接打开运行,适合用作学习参考。资源以zip压缩包提供,共57个文件、约86KB,主要包含16个cs源码文件、2个sln解决方案、2个csproj工程文件、5个resx界面资源、4个exe成品程序及pdb调试符号等,方便对照阅读和二次开发。目前已有504人学习下载。这一项目完整覆盖远程桌面的核心流程:通过Socket建立TCP连接,实现屏幕画面捕获与图像传输、键盘鼠标输入转发,并借助多线程保持界面流畅;同时涉及身份验证与数据加密等安全考量。对于想深入理解C#网络编程、远程桌面协议、或希望基于此扩展出更完整远程控制工具的开发者,都是不错的参考实例,有助于提升工程项目实践能力。 最近在折腾一套能直接跑的远程桌面应用源码,基于VS2019工程文件,拿到手里第一件事就是开箱体验"直接运行"这个承诺含金量到底有多少。实测下来,这套源码的工程组织确实做得比较规整,解决方案结构清晰,依赖项也不复杂,补上环境配置之后基本可以无缝跑起来。如果你正在找一套能快速上手的远程桌面参考实现,或者想研究Windows远程桌面底层交互逻辑,这篇文章应该能帮你省掉不少试错的成本。

项目本身的定位很明确:它不是一个简化到只能看的玩具Demo,而是包含了服务端、客户端和公共协议层的完整项目,支持基本的多会话连接、桌面画面传输、剪贴板共享和键盘鼠标事件转发。类似的源码在GitHub上并不少见,但大部分的问题是工程文件年代久远,要么还在用VS2010的项目格式,要么依赖了一堆过时的第三方库。这套源码的优势就在于VS2019的.sln/.vcxproj文件足够新,编译链干净,跑通之后再去改成VS2022或者其他工具链也更容易。

下面我按实际操作的顺序,把这套源码从工程结构到运行排错的经验完整梳理一遍。

1. 这个远程桌面源码项目到底做了什么

1.1 源码视角下的远程桌面组成

抛开mstsc.exe那个黑盒不谈,自己实现一个远程桌面应用,核心要处理的其实就四件事:画面采集、网络传输、输入注入、会话管理。这套源码在模块划分上基本就是按这个思路来的。

服务端负责抓取桌面画面,常见的做法是GDI的BitBlt截屏或者DDA(Desktop Duplication API)采集,源码里两种方式都做了封装,默认走DDA,不支持DDA的旧系统会自动回退到GDI。采集到的画面不是直接整体发给客户端,而是切分成若干矩形区域,只发变化的区域,这在带宽有限的内网环境下优势非常明显。

客户端负责接收服务端推送的画面帧,解压后绘制到本地的窗口上,同时捕获本地的键盘鼠标输入,把消息封装成自定义协议发回服务端。服务端收到后调用SendInput或模拟鼠标键盘事件。这套源码在输入转发上做了双通道设计:键盘事件走同步通道,鼠标移动走异步通道,避免鼠标操作出现明显延迟。

1.2 为什么选择VS2019工程文件

很多老牌远程桌面开源项目的通病是工程文件停留在VS2010甚至VS2008,新系统上要么装不上旧工具集,要么平台工具集不兼容导致一堆链接错误。这套源码直接用VS2019工程文件,配合Windows 10 SDK就能完成编译。

VS2019用的v142工具集对Windows 10 SDK的兼容性已经非常成熟,C++17的支持也足够完整,源码里用到std::variant、std::optional这类新特性时不会像VS2015那样报出一堆莫名其妙的模板错误。工程文件本身的配置也干净,没有硬编码的库路径和Include路径,所有依赖都是相对路径,复制到任何一台机器上解压后打开就能编译。

另外这套源码的字符集设置是对的:始终使用Unicode字符集。这一点看着不起眼,实际上是无数Windows C++项目翻车的高发区。多字节字符集下,TCHAR、TEXT宏、宽窄字符串转换到处都会埋坑,尤其是涉及网络协议序列化的时候,一个中文字符串的编码不一致就能让整个协议解析直接错位。

2. 拿到源码后如何做到"直接运行"

2.1 目录结构和方法

源码解压后,你会看到一个根目录和三个子项目。在Visual Studio 2019里直接打开解决方案文件即可,不需要单独拷贝任何静态库或DLL。三个项目的依赖关系如下:

项目类型职责依赖
RemoteServerWin32控制台程序桌面采集与服务端逻辑仅系统API
RemoteClientMFC应用连接、显示与输入捕获MFC库
RemoteProto静态库协议编解码、消息定义无
RemoteCommon静态库通用工具(编码、日志)无

RemoteProto和RemoteCommon编译成静态库,RemoteServer和RemoteClient分别链接。这种分层避免了服务端和客户端各自维护一套协议代码,改协议字段时只需要动一处。实际操作中我建议先编译整个解决方案一次,让两个静态库先输出,再分别启动服务端和客户端项目。

2.2 部署和运行

服务端和客户端必须分两台机器跑,这也是初学的时候最容易问的问题。远程桌面的本意就是"远程",你在同一台机器上跑服务端又跑客户端,连接时会出现会话冲突,因为服务端采集桌面画面时无法采集到当前交互会话之外的虚拟会话。如果只有一台电脑,可以用虚拟机跑服务端,物理机跑客户端,实测效果不错。

启动顺序是:先启动服务端,等它监听在默认端口(源码默认是5900,可以改),再启动客户端输入IP和端口。连接成功后,客户端窗口会显示服务端桌面画面。首次连接会有一个指纹确认提示,这是源码内置的简单身份校验,防止中间人连接,实际用的时候如果只想在内网快速验证,可以先跳过,但正式使用建议保留并做好客户端公钥预置。

2.3 直接运行常见的编译配置

拿到VS2019打开解决方案后,要确认三件事:平台工具集选的是v142、Windows SDK版本选了10.0(版本号根据你安装的实际情况选,源码里做的兼容性不错,10.0.17763及以上都行)、平台选的是x64。这三项不对,所谓的"直接运行"就会变成"直接报错"。

配置完成后,F6编译整个解决方案,等底部输出窗口出现"生成: 成功"的字样,就可以进入下一步了。整个过程在两台机器上操作时,记得打开Windows防火墙的TCP端口,否则客户端会一直卡在连接超时的状态。这是远程桌面类程序最常见的"外部因素",跟代码本身没关系,排查起来却特别迷惑人。

3. 编译中途遇到MSB8036错误的两个解决方向

第一个值得单独拿出来讲的坑,就是热搜词里被频繁搜索的MSB8036:找不到Windows SDK。这个问题在新装的VS2019上非常容易出现,本质是工程文件里指定的SDK版本在本机没有安装,或者VS2019没检测到已安装的SDK版本。

处理方式有两个方向:

第一个方向是安装对应版本的Windows 10 SDK。双击运行网上下载的SDK安装程序,勾选"开发人员功能"和"Windows SDK for UWP",等几分钟装完,重启VS2019,重新编译,问题一般就消失了。这个方向适合不折腾、只求赶紧跑起来的人。

第二个方向是让工程文件适配你本机已有的SDK版本。在VS2019里右键点击解决方案,选择"重定解决方案目标",弹出的对话框里会选择已安装的Windows SDK版本,确认即可。但这里要提醒的是,重定目标之后,可能引发其他连锁问题,比如某些新SDK废弃的API就编译不过了。我在评估这套源码时选择的是安装与工程文件匹配的SDK版本,把改动量降到最低。

MSB8036出现时,很多人的第一反应是去改.vcxproj文件里的TargetVersion字段,手改也行,但要注意这个字段和全局配置里的WindowsTargetPlatformVersion要保持一致,否则VS2019会顽固地坚持其缓存中的旧的版本号,清掉.vs隐藏目录里的缓存才生效。

4. 代码里藏着的坑:中文注释导致编译报错的奇怪现象

热搜词里有一条很具体的经验分享:VS2019中的.cpp等文件加入中文注释就报错。这个现象在这套源码中也出现过,你从网上下载的源码文件如果是GB2312编码,而VS2019的编辑器默认保存为UTF-8,编译时中文字符就会被错误解析,报出一堆"未声明的标识符""语法错误",错误位置指定在中文注释附近。

解决办法很简单:用VS2019打开文件,选择"文件 - 高级保存选项 - 编码UTF-8无签名的Codepage 65001",保存后再编译。文件中所有含中文字符串的源文件都要做一次这样的转换,不然会持续报错。

更稳妥的做法是在工程里加一个强制文件编码的方法。我自己习惯的做法是给解决方案根目录放一个.editorconfig文件,设定charset = utf-8,VS2019会严格按照这个配置处理新打开的文件,评论里的中文字符就不会再成为编译障碍了。

5. 踩坑过程中的完整排查链路:一次编译失败到运行时崩溃的定位复盘

为了让你对排查思路有一个整体的感觉,我完整复盘一次从编译失败到运行时崩溃的定位过程,这也是我认为这段经验比代码本身更有价值的部分。

5.1 第一反应:编译失败的输出窗口

复现问题的现象是编译大概走了十秒钟,输出窗口直接报出错:无法打开包含文件,或者某某未定义的标识符。一开始我以为又是文件编码问题,全部转成UTF-8试了一次,结果仍然失败。这时候不能继续猜了,要看完整的错误信息,也就是输出窗口里带"错误列表"页签中的"代码"和"说明"两列。

5.2 根源在MIDL生成的头文件

排查后发现,报错集中在RemoteProto项目的协议定义,那个文件实际上是MIDL生成的。网上拿到源码的通常是普通的C++开发者,很多人根本没听说过MIDL,也不了解生成的工厂头文件有个特性:需要把Windows SDK中的大量系统头文件包含进来才能通过编译。而这一步在工程默认配置下并不是自动打开的,你需要手动在项目上做一次"生成操作 - 运行MIDL编译器",才会生成完整的协议头。

这属于那种一旦知道就非常简单的坑,但不知道的时候能卡你一整天。我的排查手段是打开文件对比,发现客户端和服务端各自拿到的远程协议,在消息长度字段的定义上不一致:一个用long,一个用INT_PTR。由于系统架构是x64,long在Windows平台上占4字节,INT_PTR占8字节,两边不匹配,消息封装时缓冲区长度计算对不上,自然就崩了。

5.3 运行崩溃:缓冲区长度计算不匹配

编译过了,运行到连接建立、第一次握手成功之后,客户端窗口直接闪退。断点打在接收到第一帧画面数据的回调上,发现传入的缓冲区原始指针还在,但末尾的数据被覆盖了。按照现场堆栈反推,是解压后的位图数据长度超过预估缓冲区,写越界。

这个问题的根因和上面MIDL头文件是同一条线:协议字段类型不一致,导致客户端按错误的长度去解析包头,导致后续数据错位。这也就印证了,配置不匹配不只在编译期会产生坑,在运行期的表现更隐蔽。

5.4 排查链路小结

遇到这类源码级问题,我给一个快速定位的思路顺序:

  1. 先看编译输出窗口,对比最近一次能通过的改动;
  2. 查看协议或公共头文件中类型是否一致,在跨项目的通信代码里,类型不匹配是第一大嫌疑;
  3. 运行时崩溃用调试器看调用栈,特别关注缓冲区长度相关的API调用;
  4. 不盲目改代码,先用git或保存的备份做对比,确认每一处改动的合理性。

这个链路顺序能避开大部分方向性的错误。

6. 从"能跑"到"能用"的工程化改进

6.1 给项目添加日志与配置

源码默认把日志输出到调试器的输出窗口,在开发机上看问题不大,但一旦部署到远程服务器,窗口不可见,出事很难排查。我建议的第一步改进就是引入一个简单的文件日志模块,输出级别、目标目录、单文件大小都可以做成配置项。这一步不复杂,但对后续维护的帮助是决定性的。

配置方面还建议把连接端口、采集帧率、压缩质量、最大连接数等参数从代码里的硬编码挪到一个ini或json文件里。源码里这些参数都集中在config.h里,改动方便但不利于部署后灵活调整。封装一个全局配置类,启动时加载配置文件,运行时可以动态刷新,不仅自己的项目能用,也适用于后续在它基础上做二次开发的同学。

6.2 多会话与权限问题

如果只是两台电脑之间临时用,前面的基础版已经足够了。但如果你想把它部署成一个小型的内网远程协助工具,就需要处理多会话并存的问题。Windows的会话隔离机制决定了你的服务端程序必须运行在目标用户所在的会话里,才有权限采集对应的桌面画面。源码目前的方案是让服务端作为一个普通应用运行在当前用户会话中,这自然会限制同时被访问的场景。

改进方向有两种:一是把服务端改写成Windows服务程序,用WTSQueryUserToken获取登录用户令牌,再在对应会话里启动采集子进程;二是不改架构,只限制同一时刻只允许一个外部连接,简单粗暴,但满足大多数轻量运维需求。前者工程量大,后者更快速可靠,我个人的选择是先做后者,等确实需要用的时候再升级成服务方案。

6.3 性能观测与自检

远程桌面对流畅度的要求很直接,帧率太低,鼠标拖影严重,根本没法用。源码自带一个简单的FPS统计窗口,可以在客户端按F12呼出。实测默认参数下,局域网内1920x1080分辨率,DDA采集加JPEG压缩,画面帧率能稳定在30FPS以上;但一旦走公网,带宽变成短板,就需要在压缩率和画质之间做一个折中。

推荐的做法是在客户端显示当前帧率和网络延迟两个指标,用颜色分级表示体验等级。我之前根据实际测试把体验分成三档:延迟低于80ms且帧率高于24FPS是"流畅",延迟80~200ms是"可接受",高于200ms就要考虑降低分辨率或启用有损压缩。这个分级判断逻辑也很适合加到客户端的状态栏上,让你在远端操作时心里有底。

6.4 扩展方向

源码留给扩展的空间还不小。比如可以给客户端加上多显示器切换支持,服务端用EnumDisplayMonitors枚举当前会话的所有显示器,按需传输指定显示器的画面;也可以把协议从TCP裸流升级成TLS加密通道,避免在不可信网络上被窃听;还可以增加网络自适应码率控制,根据实时丢包率和延迟动态调整压缩质量,这一项做得好,体验提升非常明显。

如果你只是想把它当作学习参考,重点建议去读RemoteServer的桌面采集模块和RemoteClient的输入转发模块,以及RemoteProto的协议定义。这三块看懂了,远程桌面底层的基本功就算过了关,以后遇到其他类似需求也能很快迁移思路。

最后再分享一个小建议:因为我在实际使用中发现,这套源码无论在你自己的机器上测试,还是部署到内网环境里,最需要耐心的地方就是防火墙和会话权限的配置。先把这两件事理清楚,再回头调画质和帧率,会让你少走很多弯路。把这套代码保持距离多跑一段时间,你会对远程桌面的整体机制有一个非常立体、扎实的认知。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询