

WPF 窗口在 Visual Studio 调试的时候会被一个莫名其妙的调试层覆盖住
source link: https://blog.walterlv.com/post/visual-studio-add-a-window-covering-my-whole-wpf-window
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

同样的程序,在使用 Visual Studio 调试的时候和直接运行的时候相比,总会有一些细微之处是不同的。大多数时候这些不同可以忽略,但是一旦这些不同是我们产品需求的一部分的时候,你可能就会发现调试和非调试状态下的行为不同却找不到原因,非常抓狂!
本文记录我遇到的一个 WPF 窗口调试的案例。看完后大家至少知道 Visual Studio 调试时的一个小坑,更进一步则可以在出现奇妙问题的时候打开一个新的思路。
UI 自动化
微软有一款自动化办公软件 Power Automate Desktop,它可以录制你对某软件的操作,以便在后续自动化进行这些操作。
一天,我正用它来自动化操作我正在开发中的一款小工具软件(WPF 框架),但发现它竟然无法识别我界面中的任何控件,无论怎么识别,都是一整个窗口。这导致 Power Automate Desktop 的自动化操作对我正开发的软件毫无作用,这怎么能忍!
▲ 正常情况(能识别到窗口内的控件)
▲ 异常情况(只能识别到一整个窗口)
Visual Studio 干了啥!
我用 snoop 查看了一下我软件界面里的控件,发现没有什么异常。
不过,意外发现有一个名为“AdornerWindow”的窗口引起了我的注意,直接在 snoop 里将其设为隐藏后,Power Automate Desktop 瞬间即可正常识别我软件里面的各种控件了。
▲ 引起注意的“AdornerWindow”窗口
然而,我不能每次自动化之前先用 snoop 隐藏一下这个窗口吧,所以就打算在我窗口的 ContentRendered
事件里把它干掉。这就有了下面这段代码:
public MainWindow()
{
InitializeComponent();
ContentRendered += RecordingCaptureWindow_ContentRendered;
}
private void RecordingCaptureWindow_ContentRendered(object? sender, EventArgs e)
{
HandleVisualStudioHacking();
}
/// <summary>
/// 因为 Visual Studio 会在调试状态下向此窗口添加一个全覆盖窗口,导致我们无法捕获到下方控件。所以我们需要将此窗口移除。
/// </summary>
[Conditional("DEBUG")]
private void HandleVisualStudioHacking()
{
var windows = Application.Current.Windows.OfType<Window>().ToList();
var thisWindowIndex = windows.IndexOf(this);
var suspiciousWindowIndex = thisWindowIndex + 1;
if (suspiciousWindowIndex < windows.Count
&& windows[suspiciousWindowIndex] is { } suspiciousWindow
&& suspiciousWindow.GetType().FullName == "Microsoft.VisualStudio.DesignTools.WpfTap.WpfVisualTreeService.Adorners.AdornerWindow")
{
suspiciousWindow.Close();
}
}
因为发现每一个 WPF 窗口上面都会覆盖这样一个透明窗口,所以我拿到主线程所有窗口的列表,找到当前窗口的下一个(因为假想 Visual Studio 总会在我们创建完一个窗口后立即创建覆盖窗口),然后把它关掉。
本文会经常更新,请阅读原文: https://blog.walterlv.com/post/visual-studio-add-a-window-covering-my-whole-wpf-window ,以避免陈旧错误知识的误导,同时有更好的阅读体验。
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 吕毅 (包含链接: https://blog.walterlv.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 ([email protected]) 。
Recommend
-
223
技术成就梦想51CTO-中国领先的IT技术网站 您浏览的内容找不到或已被删除
-
75
免费蹭网背后 被莫名其妙薅羊毛免费蹭网背后 被莫名其妙薅羊毛熊出墨请注意2017-11-21 20:53优质...
-
76
公共WiFi变现产业链调查:免费蹭网背后,被莫名其妙薅羊毛熊出墨请注意·2017-11-22 01:57通过公共WIFI“蹭网”,可能真的会把个人信息“蹭”得满大街都是。
-
37
-
30
写在前面:假定你在日常的工作中使用到了Visual Studio,并期望了解一些调试技巧来提高工作效率,也许本文适合你。以下Visual Studio简称vs。 一、入门 以最简单的控制...
-
22
这两天,写了个小小的 Python 代码,基本功能实现了,需要完善一下的时候,突然想起来,VS Code 那么好用,应该也支持 Python 吧,我就不用在命令行用 vim 写那么辛苦了,主要是对中文字符的渲染不好看。 没想到,相当尴尬了,用 V...
-
18
有趣的阅读 - 12个提高生产力的Visual Studio调试技巧计算机图形学话题下的优秀回答者前因为工作的关系,接触过不少程序员同行,发现很多同学对所谓的小技巧tips感兴趣。本文就是...
-
6
您是否曾经需要调试并进入依赖于 NuGet 或 .NET 库的代码,而这些库并没有构建为您的解决方案的一部分? 现在,调试它们并不像调试作为解决方案一部分的项目那么容易。从 Visual Studio 2022 预览3开始,我们在解决方案资源管理器中添加了一个新的“External...
-
5
在Visual Studio中调试Linux控制台程序 作者:漫漫开发路 2023-02-02 09:33:04 在预览版中,使用嵌入到集成终端中的 Linux 控制台,Visual Studio 在调试 Linux 应用程序时支持功能齐全的类似 Linux 终端的体验。...
-
4
虽然异步代码可以提高程序的整体吞吐量,但异步代码仍然无法免除错误!当潜在的死锁、模糊的错误消息以及查找导致 Bug 的 Task 时,编写异步代码会使调试更加困难。幸运的是,Visual Studio 具有与托管的、本地的和 JavaScript 兼...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK