You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

关于RDP场景下及Windows软件中实现客户端黑屏以阻止屏幕共享的技术咨询

RDP场景下Windows软件实现客户端屏幕共享黑屏的解决方案

问得好!我来帮你拆解Windows下怎么实现这个需求——让普通屏幕共享工具(比如TeamViewer、AnyDesk、QQ远程这类)连接主机时看到黑屏,但完全不影响RDP远程桌面的正常使用。下面给你几个靠谱的方法,从系统原生设置到定制代码思路都有:

方法一:利用Windows会话隔离的原生机制

Windows的RDP使用独立的终端服务会话,而绝大多数普通屏幕共享工具只会捕获当前的本地交互会话(控制台会话)。我们可以通过设置让控制台会话固定显示黑屏,同时让RDP会话正常加载桌面:

  • 先制作一张纯黑色的BMP图片,命名为black_screen.bmp,保存到C:\Windows\System32\目录下
  • 打开注册表编辑器regedit,定位到路径:HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
  • 修改Shell键值为mspaint.exe C:\Windows\System32\black_screen.bmp(用画图程序全屏显示黑屏图片)
  • 这样设置后,本地控制台会话登录后会直接显示黑屏,但RDP连接时会自动创建新的远程会话,加载正常的桌面环境,完全不受影响。
  • 注意:确保RDP没有启用“连接到控制台会话”(默认是关闭的,可通过组策略计算机配置>管理模板>Windows组件>远程桌面服务>远程桌面会话主机>连接>限制连接到控制台会话确认)

方法二:用虚拟显示器分离RDP与本地显示

这个方法更灵活,适合需要动态切换的场景:

  • 安装虚拟显示器工具,比如DisplayFusion、开源的Virtual Display Adapter,或者Windows 11自带的“无线显示”功能(需开启后添加虚拟显示器)
  • 配置RDP连接强制使用虚拟显示器:在RDP客户端的“显示”设置中选择虚拟显示器作为输出目标;或者在主机端通过组策略计算机配置>管理模板>Windows组件>远程桌面服务>远程桌面会话主机>远程会话环境>限制最大远程桌面服务显示分辨率,指定虚拟显示器的分辨率
  • 把物理显示器的显示设置调整为“仅在虚拟显示器上输出”,或者直接让物理显示器显示黑屏(设置纯黑桌面背景、隐藏所有桌面图标和任务栏)
  • 此时普通屏幕共享工具捕获的是物理显示器的黑屏画面,而RDP连接的是虚拟显示器的正常桌面。

方法三:定制软件的API拦截实现

如果你的软件需要动态检测屏幕共享并触发黑屏,可以通过Hook系统的屏幕捕获API来实现:

  • 核心思路:Hook GDI中的BitBltStretchBlt,或者Win10+的Windows Graphics Capture API,在回调中区分RDP进程和其他屏幕共享进程
  • 具体实现可以用C++配合Detours库,或者C#的EasyHook库。举个简单的伪代码示例:
// Hook GDI的BitBlt函数
BOOL WINAPI HookedBitBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, DWORD dwRop) {
    // 获取当前调用捕获操作的进程名称
    TCHAR procName[MAX_PATH];
    GetModuleFileName(NULL, procName, MAX_PATH);
    std::wstring procStr(procName);
    
    // 放行RDP相关进程的捕获请求
    if (procStr.find(L"mstsc.exe") == std::wstring::npos && procStr.find(L"rdpclip.exe") == std::wstring::npos) {
        // 对其他进程返回黑屏:用黑色填充目标DC
        HBRUSH blackBrush = CreateSolidBrush(RGB(0, 0, 0));
        RECT rect = {nXDest, nYDest, nXDest + nWidth, nYDest + nHeight};
        FillRect(hdcDest, &rect, blackBrush);
        DeleteObject(blackBrush);
        return TRUE;
    }
    // 对RDP进程放行,调用原函数
    return OriginalBitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, dwRop);
}

额外注意事项

  • 多工具适配测试:不同屏幕共享工具可能用不同的捕获方式(GDI/DirectX/Windows Graphics Capture),可能需要同时Hook多种API
  • 权限要求:Hook系统API的软件需要以管理员权限运行,否则无法拦截所有进程的捕获操作
  • RDP会话验证:测试时用不同账号登录RDP,确保不会和控制台会话冲突

备注:内容来源于stack exchange,提问作者pmugzz

火山引擎 最新活动