WPF 通过 SetWindowDisplayAffinity 配置禁止对窗口进行截图或录屏

news/2024/10/4 19:21:54

有些应用程序比较机密或隐私,不期望被其他截图软件截图到应用的窗口,或者被录屏软件录制到。简单的方法是通过 SetWindowDisplayAffinity 方法进行配置窗口阻止截图软件对其截图

开始之前必须说明的是对抗截图录屏是一个矛和盾的事情,截图和录屏技术方向在千方百计尝试对所有窗口进行截图和录屏。而某些机密或隐私等软件又在对抗截图和录屏。本文使用的 SetWindowDisplayAffinity 只是一个非常基础的禁止窗口被截图的方法,能防住的截图工具和录屏软件有限,只能做简单的保护窗口不被基础截图工具所获取界面

按照使用 Win32 方法的惯例,先定义出来 SetWindowDisplayAffinity 方法,代码如下

    private const uint WDA_NONE = 0x00000000;private const uint WDA_MONITOR = 0x00000001;[DllImport("user32.dll")]public static extern uint SetWindowDisplayAffinity(IntPtr hWnd, uint dwAffinity);

在 .NET 7 之后,还可以使用 LibraryImportAttribute 这个源代码生成器辅助的定义 Win32 方法,对比 DllImport 的优势在于能够通过源代码生成器优化调用的性能。更新之后的定义代码如下,核心是将 extern 换成 partial 关键词和更换标记的特性

    [LibraryImport("user32.dll")]public static partial uint SetWindowDisplayAffinity(IntPtr hWnd, uint dwAffinity);

对于本文使用的如此简单的 SetWindowDisplayAffinity 方法,使用 LibraryImportAttribute 是没有带来什么好处的

且使用此特性需要给当前的项目开启不安全代码的允许开关。更多请参考 P/Invoke source generation - .NET Microsoft Learn

为了方便本文描述,我新建了一个例子项目,可以在本文末尾找到本文所有代码的下载方法

在 MainWindow.xaml 放一个按钮,用于控制设置窗口允许和禁止截图的状态

        <ToggleButton x:Name="TakeSnapshotToggleButton" HorizontalAlignment="Center" VerticalAlignment="Center" Padding="10,10,10,10" Content="禁止截图" Checked="TakeSnapshotToggleButton_OnChecked"/>

后台代码编写实现逻辑

    private void TakeSnapshotToggleButton_OnChecked(object sender, RoutedEventArgs e){if (TakeSnapshotToggleButton.IsChecked is true){// 禁止截图模式SetWindowDisplayAffinity(new WindowInteropHelper(this).Handle, WDA_MONITOR);// 修改内容为再点击就是允许截图TakeSnapshotToggleButton.Content = "允许截图";}else{// 允许截图模式SetWindowDisplayAffinity(new WindowInteropHelper(this).Handle, WDA_NONE);// 修改内容为再点击就是禁止截图TakeSnapshotToggleButton.Content = "禁止截图";}}

如此即可实现此按钮功能,尝试运行代码,点击按钮,进入禁止截图状态。然后使用截图软件,如 QQ 截图等工具尝试进行截图,可以看到窗口是黑的不能被截图

接着再点击按钮,进入允许截图状态,此时可以看到截图软件可以对窗口进行截图可以看到窗口的内容

通过本文的方法只能防御有限的截图软件。有些从驱动级进行获取界面图像的,或者 Hook 掉 DWM 的,甚至更彻底的从 HDMI 级硬件捕获的,这些都统统无法防御

在 Windows 10 的 2004 版本,对 SetWindowDisplayAffinity 方法进行了扩展,添加了只允许在显示器显示而不在任何截图或录屏工具显示的参数。在原先的 SetWindowDisplayAffinity 使用 WDA_MONITOR 禁止截图时,使用截图工具将看到一个黑色的窗口,看不到任何内容。但是对于一些录屏软件来说,会影响其体验。有时候期望做一个录屏辅助工具,却要么发现录屏辅助工具被录屏工具录制进去,要么就是黑色一片影响交互。通过新的 WDA_EXCLUDEFROMCAPTURE 参数,可以有效进行优化

使用 WDA_EXCLUDEFROMCAPTURE 参数,可以配置应用窗口只允许在显示器显示而不在任何截图或录屏工具显示,这就意味着窗口对于截图软件录屏软件来说是隐藏的,从截图软件里面不再可以看到应用窗口,截图软件不会看到黑色的窗口而是完全不知道有这样的窗口的存在

使用方法也非常简单,如以下代码

SetWindowDisplayAffinity(new WindowInteropHelper(this).Handle, WDA_EXCLUDEFROMCAPTURE);private const uint WDA_EXCLUDEFROMCAPTURE = 0x00000011;[DllImport("user32.dll")]public static extern uint SetWindowDisplayAffinity(IntPtr hWnd, uint dwAffinity);

大家可以运行代码,测试一些分别设置 WDA_MONITOR 和 WDA_EXCLUDEFROMCAPTURE 参数,对截图软件的影响

特别说明的是,只有在 Windows 10 的 2004 和更高版本,才能支持 WDA_EXCLUDEFROMCAPTURE 参数。如果在更低的版本运行,则 WDA_EXCLUDEFROMCAPTURE 参数的功能和 WDA_MONITOR 相同

本文代码放在 github 和 gitee 上,可以使用如下命令行拉取代码

先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 21c1500cd1ca8bffe892644425235de7eac24f92

以上使用的是 gitee 的源,如果 gitee 不能访问导致拉取失败,请替换为 github 的源。请在命令行继续输入以下代码,将 gitee 源换成 github 源进行拉取代码

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin 21c1500cd1ca8bffe892644425235de7eac24f92

获取代码之后,进入 WPFDemo/LecacheniJequchaferenal 文件夹,即可获取到源代码

参考文档

P/Invoke source generation - .NET Microsoft Learn

https://github.com/akinbicer/screen-capture-protector

SetWindowDisplayAffinity function (winuser.h) - Win32 apps Microsoft Learn

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/44220.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

[转帖]性能分析之TCP全连接队列占满问题分析及优化过程

https://cloud.tencent.com/developer/article/1558493 前言 在对一个挡板系统进行测试时,遇到一个由于TCP全连接队列被占满而影响系统性能的问题,这里记录下如何进行分析及解决的。 理解下TCP建立连接过程与队列 从图中明显可以看出建立 TCP 连接的时候,有两个队列:syns…

Linux内核版本以及部分参数与性能之二

Linux内核版本以及部分参数与性能之二版本范围 grubby --set-default /boot/vmlinuz-6.9.4-1.el7.elrepo.x86_64 grubby --set-default /boot/vmlinuz-5.4.277-1.el7.elrepo.x86_64 grubby --set-default /boot/vmlinuz-4.19.12-1.el7.elrepo.x86_64 grubby --set-default /boo…

Python实用库--PrettyTable

简介 PrettyTable是一个强大的Python第三方库,专门设计用于从程序中生成美观、易于阅读的ASCII格式表格。 在数据分析、命令行工具开发、脚本编写等领域中,特别是在需要直观呈现数据而又不依赖图形界面的情况下,PrettyTable库显得尤为实用。 其设计灵感来源于PostgreSQL的ps…

随便写的小网页练习

随便写的小网页练习: 👆原视频:十分钟学会写网页【编程前端入门】 本期重做了好几遍,是全新的视角和概念,从浏览器底层渲染原理到实现网站的演示,一节课讲透,必看的一期。后面不管是写小程序还是App,都会用到这一期的概念。 这一期内容是我做完第一章个人网站后更新的,…

golang 同时(一个项目)注册http和GRPC服务

main 里面package mainimport ("fmt""github.com/gin-gonic/gin""github.com/hashicorp/consul/api"grpc "gorm_project/grpc/services""gorm_project/route""gorm_project/utils""log""net/http&…

如何设置word首页封面不出现页眉和编码

方法: 比如说我想让页码从第二页开始编号,那就双击第二页的编号,然后勾取消掉这个链接到前一页(我这里已经勾选掉了),之后直接删除掉第一页的编号就可以了如果数字不对的话,可以在“设置页码格式”中修改一下起始的页码:参考: 设置word中第一页不显示页码,第二页页码…

Paimon笔记

支持高吞吐数据摄入、变更追踪、高效分析的流批数据湖 基于LSM提升写入速度并降低写入消耗;基于有序的SortRun裁剪大部分数据以提升查询性能;支持多种merge引擎实现高性能流表打宽 基于Flink&Paimon实现,提供数据一致性管理能力,解决流式数仓普遍存在的问题 paimon通过…

6.14安卓开发日记58

实验三:Newton法程序设计 一、实验目的 掌握Hesse矩阵的计算方法和Newton法的基本思想及其迭代步骤;学会运用MATLAB编程实现常用优化算法;能够正确处理实验数据和分析实验结果及调试程序。 二、实验内容 (1)求解无约束优化问题:; (2)终止准则取; (3)完成Newton法(…