所以 window tray 的这个 bug,从 win95 一直延续到 win11? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
phpfpm
V2EX    Windows

所以 window tray 的这个 bug,从 win95 一直延续到 win11?

  •  
  •   phpfpm 2022-01-28 23:46:42 +08:00 5117 次点击
    这是一个创建于 1434 天前的主题,其中的信息可能经有所发展或是发生改变。

    一个在 tray 里面的程序,如果被 kill 掉没有 gracefully 退出,那么就会一直残留在 tray

    喵喵喵??? M$觉得这个是个 feature 么????

    18 条回复    2022-01-30 02:57:27 +08:00
    Osk
        1
    Osk  
       2022-01-29 00:49:31 +08:00
    想不到是祖传 bug, 鼠标晃一下就能消失, 不过有时很干扰.
    moen
        2
    moen  
       2022-01-29 00:51:34 +08:00   3
    严格上说这是机制的问题,不算 bug 。Notification icon 的创建和删除都是由应用程序自己 Push 给 explorer.exe ,但 explorer.exe 方面并没有设计一套 Pull 机制来主动了解 notification icon 所属的进程是否存在。所以进程崩溃了没法自行删除,就一直显示在那里了。而 explorer.exe 崩溃后 notification icon 不会重建也是因为这套机制导致的

    至于为什么一直不加我不知道
    imn1
        3
    imn1  
       2022-01-29 03:16:00 +08:00
    我自己写的一个 GUI 程序,测试时试过残留了几十个图标,每运行就生成一个,崩了就留下……
    kkocdko
        4
    kkocdko  
       2022-01-29 06:14:26 +08:00 via Android
    @moen 但是鼠标移上去就消失了,我对 windows 开发不熟悉,推测这大概是 mouseover ,然后向应用请求获得 tooltips ,结果发现没有回应,就知道应用推出了。

    那为什么不能隔一段时间轮询呢?难道是历史遗留问题,怕某些应用获取一次 tooltips 要花很多时间?或者某些应用依赖这种行为?
    geelaw
        5
    geelaw  
       2022-01-29 07:45:09 +08:00   12
    首先,那个东西叫“通知区域”,不叫 tray 。即使你认为 tray 来自于早期代码里的命名,tray 也是指整个任务栏。

    这个问题的成因是通知区域图标是程序通知任务栏创建的,崩溃时程序没有通知删除,所以不会立刻消失。

    鼠标放上去会消失是因为 Explorer 会给图标对应的窗口发消息,如果窗口句柄已经无效,则会删除图标注意窗口句柄是 USER 句柄,因此既没有计数也会复用,在极限情况下可能新程序被分配到已经崩溃程序使用过的句柄,导致新程序莫名其妙收到消息。

    Explorer 崩溃重启后程序需要重新添加图标,获取这一信息的方法是注册“任务栏创建好了”消息。

    为什么不能轮询因为不存在一个“心跳”消息,也不应该随便给窗口发送消息(虽然理论上可以注册一个新名字,这样任意窗口都不会对该消息有特殊反应才对),也不应该轮询(性能问题)。

    这个问题显然是可以解决的,比如任务栏上列举窗口的按钮可以对崩溃立刻作出反应,这个变化是 USER 监控,并发送 WM_SHELL_* 消息给任务栏的。然而通知区域图标并不是 USER 概念而是 shell 概念(只存在于 explorer.exe 进程中),虽然可以提升到 USER 概念实现之,估计是不值得吧( USER 是 per-session 级别的,可以容纳的句柄数量也相当有限)。

    更好的解决方法是不要崩溃。

    类似的问题也存在于 Application Desktop Toolbar 。还有更多设计 bug 导致 shell 的一些部分需要两次操作才能刷新( COM categories 、shellnew 等)。
    yulon
        6
    yulon  
       2022-01-29 07:48:54 +08:00
    进程创建销毁的事件依赖内核态,所以内核资源比如文件网络都可以自动释放,你要监控就得写个驱动。

    GUI 资源一般是用户态的窗口消息管理的,他就是逼你正确处理窗口消息,不要越过 GUI 直接终止进程。

    既然已经有事件的方法了,再加个轮询就显得有点脏,当然这都是设计问题,人家就是这么规定的。
    ysc3839
        7
    ysc3839  
       2022-01-29 08:14:55 +08:00
    @geelaw 一种可行的方案是检测窗口对应的进程,这样不需要轮询,也不会有复用问题,缺点是没法解决进程没退出,窗口关闭但忘记删除 notification icon 的情况。
    caocong
        8
    caocong  
       2022-01-29 09:35:27 +08:00
    或许微软觉得这问题是应用的问题不是他的问题
    coolcfan
        9
    coolcfan  
       2022-01-29 10:07:30 +08:00
    网易 UU 正常点退出都会留图标在通知区域……
    geelaw
        10
    geelaw  
       2022-01-29 10:37:08 +08:00 via iPhone
    @ysc3839 #7 这是不行的,因为通知区域图标关联的窗口可能是高权限进程(或者另一个非管理员用户的进程),窗口消息仍然可以送达( Explorer 有 UIAccess ),但 Explorer 无权访问该进程。此外关联窗口可以变更,要恰当实现等待进程结束还是挺复杂的(需要用 WaitForMultipleObjects 技巧)。
    imn1
        11
    imn1  
       2022-01-29 12:24:00 +08:00
    @ysc3839 #7
    不一定是主进程创建的图标,引申:同一个程序也可以创建多个图标(例如火绒),这样要检查的可能太多了

    @coolcfan #9
    没用过这个,但我怀疑有驻留程序,只是主窗口关闭而已,“国产”很多类似情况,如迅雷、百度云管家
    dandycheung
        12
    dandycheung  
       2022-01-29 14:43:10 +08:00 via Android
    @geelaw 没有查资料,凭记忆瞎聊两句。1. 通知区域自从出现就是叫 tray ,当时翻译过来多数译作“托盘”。2. 用 TaskbarCreated 字符串注册出来是消息是后加的,不是一开始就有。3. 不要崩溃结局不了所有问题,有时候是被别人杀死的。4. 还有,有一个 Windows 消息,叫 WM_NULL ,似乎真需要的话,可以废物利用一下。
    CallMeReznov
        13
    CallMeReznov  
       2022-01-29 15:30:29 +08:00
    LxnChan
        14
    LxnChan  
       2022-01-29 16:40:07 +08:00
    @imn1 俺也一样
    @kkocdko 这个应该就是刻意没有做轮询,本身删除托盘图标的操作就是应该由程序本身发起而不是系统去做,一是性能问题二是万一当前 explorer 没有权限访问该程序(也可能是服务)就误以为该程序已经关闭甚至 explorer 直接崩溃
    @CallMeReznov 草哈哈哈
    ysc3839
        15
    ysc3839  
       2022-01-29 22:27:39 +08:00 via Android
    @geelaw 印象中 OpenProcess SYNCHRONIZE 好像不受权限限制吧?关联窗口变更后监视新窗口对应的进程就行了。
    @imn1 我没明白这是什么问题。
    @dandycheung 你的说法是错的,自从出现就是 Shell Notify Icon 。这篇文章 https://devblogs.microsoft.com/oldnewthing/20030910-00/?p=42583 也给出了一些理由。
    imn1
        16
    imn1  
       2022-01-29 23:08:50 +08:00
    @ysc3839 #15
    简单说,就是窗口、trayicon 、进程不是唯一对应的,例如主进程带出两个子进程,一个创建窗口,一个创建 trayicon……以此类推,还可能有第二、第三……窗口,第二、第三……trayicon ,这样检测其中某个窗口并不能确定它对应的 trayicon
    ysc3839
        17
    ysc3839  
       2022-01-29 23:18:03 +08:00 via Android
    @imn1 只需要监测接收 icon 消息的窗口所属的进程就行了呀,跟主进程子进程以及它们创建了多少窗口什么的都没关系。
    FrankHB
        18
    FrankHB  
       2022-01-30 02:57:27 +08:00
    进来就盲猜这个问题,果然……

    就算不是 feature ,怕是也周知到能当作 feature 了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2375 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 36ms UTC 10:19 PVG 18:19 LAX 02:19 JFK 05:19
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86