一次应用程序窃取焦点问题排查经历

一、问题背景

忙碌的夜晚,我喝着拿铁,坐在电脑旁,在指尖且飞快的敲着键盘的时候,键盘突然打不了字,window窗口栏变灰,应该是窗口失焦了,此时只需要动动鼠标,点击窗口恢复焦点,就可以继续愉悦的敲键盘了。

此起彼伏,窗口又失去了焦点,双手已然在键盘位只能再去移动鼠标..点击窗口…..

周而复始几次后,我终于忍不住了。。

二、问题确认

问题具有随机性、可复现,在排除了“可能不小心按错键导致失焦”的可能性后。

我就把问题的关键词确认在 “window11” “窗口失焦”

三、SFW(Seach in Fxxking Web)方法

得到了的关键词,开始了从互联网找答案。

z95LUP.png

通过一番操作后,仍然得不到任何有用的信息。

四、问题重新分析、猜测

互联网找不到答案,从问题根源入手。

由我目前的前置知识得知:

Force Window to Always Be in Focus
// window必然会有一个窗口焦点

但从我的现象来看,失焦的时刻并没有其他页面弹出,所以猜测焦点可能被后台程序获取了?传说中的"焦点窃取"?

经过重新分析后,我确定下一步方向:找到窃取焦点的进程。

去Web查询窗口焦点的资料,发现了一个软件ViewWizard,不仅可以捕捉到窗口的句柄,还能捕捉到窗口的pid。

但是使用起来没有那么理想:失去焦点时并没有捕捉到。

所以我找到了一篇博客:用亲切的C#实现的window api 获取 当前焦点窗口的信息,根据博客提供的思路和window API ,写出获取窗口句柄的代码。

https://www.cnblogs.com/mq0036/p/12575627.html

代码完成后,执行程序,尝试复现问题。果不其然,窗口被一个叫TscShellContainerClass的窗口捕捉了。

z95Tud.jpg

再用回软件ViewWizard根据句柄查询PID。

知道了PID后,再通过命令查询线程的信息:

taskList|findstr XXXX

z95jC8.md.png

?这不是远程桌面的应用程序吗?他捕捉我焦点干嘛捏?

五、问题怎么产生、根源

  • 通过process Manage,定位问题发生瞬间的调用信息

    从mstu.exe的调用树已经几乎可以确认是WSL的锅了。

z95v8S.md.png

自己平时也不会去用远程桌面,这个功能也是我前段时间为了能使用WSLg才打开的。

并且问题发生的时刻,我没有主动去开启远程桌面程序,不过我WSLg默认是启动的,还是不明白问题的原因。

于是在确定了导致问题发生的mstsc,开始SFW

六、问题追溯

线索一:mstsc.exe

mstsc.exe stealing focus(mstsc.exe窃取了焦点)

https://answers.microsoft.com/en-us/windows/forum/all/mstscexe-stealing-focus/f9acb6fd-3c95-4e22-8f40-dc41dffbb178

z95xgg.md.png

z95zvQ.png

帖子最终结果为官方也不知道。。当事人自己删除了wslg才临时解决问题。。

不过通过这一线索,基本可以确认问题出现在window 和 SubSystem linux 之间

线索二:Windows Subsystem for Linux GUI和mstsc.exe之间的联系

z9IwVI.jpg

通过搜索得知,微软在WSLg System Distro里加了远程桌面服务套件——FreeRDP,一个支持Windows远程桌面协议(RDP)的服务端.

整个WSLg System Distro、Windows远程桌面客户端(mstsc.exe)的窗口都是对用户隐藏的,猜测是用户开启WSL或者敲完Linux GUI程序名的时候,这些隐藏的组件就已经在后台运行了。具体来说就是上图的WSLGd,微软解释说一个类似守护进程的程序,负责启动Weston、建立RDP通信等工作,如果它们挂了的话还要负责重启它们。

线索三、问题在于window通过RDP向WSL通信时

z9IrPf.png

通过这一线索和开源的信息得知,当一些内容到shot(剪切板)时,负责RDP的线程发生崩溃。

最后发现了这个问题的issue:

z9Ipuj.png

z9I9Ds.png

官方解释和结论

由于从 FreeRDP 线程到 wayland 显示循环线程的多线程切换而导致事件源为 NULL,导致崩溃。

z9oAeA.png

  • 提供了临时解决的方案—关闭WSLg :)