Windows7下“僵尸”图标的解决方案

从《一种清除windows通知区域“僵尸”图标的方案——问题分析》(以后简称《问题分析》)一文中分析的通知区域结构可以看出,Windows7的通知区域比XP通知区域多出了一个“临时”系统通知区域(转载请指明出于breaksoftware的csdn博客)

虽然我们可以在“控制面板\所有控制面板项\通知区域图标”下选择“始终在任务栏上显示所有图标和通知(A)”,来让Windows7的通知区域和XP上一致,但是我们无法让用户这么去做,因为我们给不出这样做的必要。

这个隐藏的通知区域是让我非常头疼的,《一种清除windows通知区域“僵尸”图标的方案——XP系统解决方案》一文中的所有方案都不适用于它。

在各种方法走不通的情况下,我们不妨换一种思路:保证只有一个图标。如果进程意外退出,那么在下次启动时,再次注册和新增通知区域图标时,我们先删掉原来的图标然后再新增图标,而不是简单的新增一个图标。或许有人会问,为什么XP下不这么做呢?因为XP下无法删除其他进程创建的图标。

XP下密集出现的“僵尸”图标问题,应该是引起了微软的注意。所以他们在Vista之后的系统中,给通知区域图标新增了一个GUID信息。于是,我们就可以简单的指定GUID便可以保证了图标的唯一性!

    m_NotifyIcon.cbSize = sizeof(m_NotifyIcon);m_NotifyIcon.uFlags = NIF_ICON | NIF_TIP;if ( bWin7OrLater ) {GUID PathGUID = {0x23977b55, 0x10e0, 0x4041, {0xb8, 0x62, 0xb1, 0x95, 0x41, 0x96, 0x36, 0x69}};m_NotifyIcon.guidItem = PathGUID;m_NotifyIcon.uVersion = NOTIFYICON_VERSION_4;m_NotifyIcon.uFlags |= NIF_GUID;}m_NotifyIcon.hWnd = m_hWnd;m_NotifyIcon.hIcon = m_hIcon;

看似这个问题就这么解决了,但是问题绝对不是这么简单的。我们发现,如果我们将程序A拷贝到其他目录下叫作A‘。如果A'创建了图标,并且A'进程被杀死。那么A进程可能出现无法创建和无法删除图标的情况,这样就严重影响了正常执行流程。

其实这个问题也比较好解决:去掉hWnd参数的指定。但是这个方案将导致一个缺陷:通知区域图标不能将消息传递给主界面!

一个比较好的解决方法,就是让不同目录下进程新增的图标的GUID不同。于是我们可以计算当前进程路径的MD5,方法是

……if ( bWin7OrLater ) {WCHAR wcharPath[MAX_PATH] = {0};DWORD dwSize = GetModuleFileName(NULL, wcharPath, ARRAYSIZE(wcharPath) );unsigned char md5[16] = {0};GetMD5((const unsigned char*)wcharPath, dwSize * sizeof(WCHAR), md5, sizeof(md5));GUID PathGUID;// = {0x23977b55, 0x10e0, 0x4041, {0xb8, 0x62, 0xb1, 0x95, 0x41, 0x96, 0x36, 0x69}};memcpy_s(&PathGUID, sizeof(GUID), md5, sizeof(md5));
……}

创建图标的方法是

VOID CNotificationIconDlg::ShowTrayIcon()
{if ( FALSE == Shell_NotifyIcon(NIM_ADD, &m_NotifyIcon) ) {if ( ERROR_NO_TOKEN == ::GetLastError()) {for ( int i = 0; i < 64; i++) {if ( FALSE == Shell_NotifyIcon(NIM_DELETE, &m_NotifyIcon) ) {if ( ERROR_TIMEOUT == ::GetLastError() ) {break;}}}if ( FALSE == Shell_NotifyIcon(NIM_ADD, &m_NotifyIcon)) {if ( ERROR_NO_TOKEN == ::GetLastError()) {m_NotifyIcon.uFlags ^= NIF_GUID;}if ( FALSE == Shell_NotifyIcon(NIM_ADD, &m_NotifyIcon) ) {}}}}
}

至此,Windows7下的图标问题也就解决了。这儿再记录一份使用advapi.dll中相关方法计算MD5的代码

#include "stdafx.h"
#include "WinMd5.h"BOOL GetMD5(const unsigned char * buf, unsigned int unbufferlenth, unsigned char* retMd5, unsigned int unMd5BufferSize)
{BOOL bSuc = FALSE;HINSTANCE hDLL = NULL;do {MD5_CTX ctx;if ( unMd5BufferSize > sizeof(ctx.digest) ){break;}HMODULE hDLL = LoadLibrary(L"advapi32.dll");if ( NULL == hDLL ) {break;}PMD5Init MD5Init = (PMD5Init)GetProcAddress(hDLL, "MD5Init");PMD5Update MD5Update = (PMD5Update)GetProcAddress(hDLL, "MD5Update");PMD5Final MD5Final = (PMD5Final)GetProcAddress(hDLL, "MD5Final");if ( !MD5Init || !MD5Update || !MD5Final ) {break;}MD5Init(&ctx);MD5Update(&ctx, buf, unbufferlenth);MD5Final(&ctx);memcpy_s(retMd5, unMd5BufferSize, ctx.digest, sizeof(ctx.digest)); bSuc = TRUE;} while (0);if ( NULL != hDLL ) {FreeLibrary(hDLL);hDLL = NULL;}return bSuc;}

最后附上工程地址

一种清除windows通知区域“僵尸”图标的方案——Windows7系统解决方案相关推荐

  1. 一种清除windows通知区域“僵尸”图标的方案——XP系统解决方案

    XP下"僵尸"图标的解决方案 从<一种清除windows通知区域"僵尸"图标的方案--问题分析>(以后简称<问题分析>)一文中分析的通知 ...

  2. 一种清除windows通知区域“僵尸”图标的方案——问题分析

    通知区域名称有趣的历史 假如说到windows通知区域,可能很多人还是不清楚它是什么.如果改称Tray区域,可能有人就懂了.如果再白话点,叫它"托盘"或者"系统托盘&qu ...

  3. 28、Windows API Shell任务栏通知区域(Tray)图标

    使用了通知区域图标的程序应该是图形用户界面的程序,具有窗口,和一般的窗口程序一样,应该创建一个主窗口,并处理窗口消息. 一.相关API 1.Shell_NotifyIcon Sends a messa ...

  4. Windows 10任务栏中托盘区(通知区域)图标怎么缩略成^

    1.重启电脑后windows的通知区域就不能缩略了,有些图标还没有,用了这个办法才重新显示.但是图标不能缩略看着很不习惯. Windows 10任务栏中托盘区(通知区域)图标消失的解决方法_Ayka的 ...

  5. 【转】PB实现在通知区域添加图标

    "为应用程序在任务栏通知区域加个图标,按最小化控制菜单后隐藏窗口,单击通知区域内的图标恢复并显示窗口,右击通知区域内的图标弹出快捷方式菜单",已成为时下程序设计上的一个时髦主题,有 ...

  6. Windows 10任务栏中托盘区(通知区域)图标消失的解决方法

    该方法仅使用于部分情况.首先参考了win10系统托盘图标不见了_Win10任务栏托盘区域图标异常怎么办?任务栏通知区域重置方法...一文重置了通知区域TrayNotify的注册表,然而没有见效.通过尝 ...

  7. windows 7编辑启动菜单 bcdedit linux,windows7系统下删除wubi安装的ubuntu启动项使用命令bcdedit解决...

    windows7系统下删除wubi安装的ubuntu启动项使用命令bcdedit解决 发布时间:2013-05-28 15:19:31   作者:佚名   我要评论 前不久用笔记本通过wubi安装Ub ...

  8. Windows 7 自动更新失败导致无法进系统解决方案

    故障现象:自动更新后,重启电脑,提示: (配置Windows update 失败 还原更改 请勿关闭计算机), 而计算机一直停留该界面,如果半个小时以上都无反应.此时,就不要再继续等待了.可采取以下办 ...

  9. win10系统托盘图标不见了_Win10任务栏托盘区域图标异常怎么办?任务栏通知区域重置方法...

    经常使用Win10系统的用户说,任务栏通知区域的图标异常已不是什么新鲜事.据分析,Win10任务栏通知区域异常是在两种情况下发生的:其一为声音.网络.电池等图标出现无法启用,而导致图标异常:其二是因为 ...

最新文章

  1. 服务器虚拟化北向,KVM虚拟化的部署及使用
  2. 2020-08-23logloss对数损失函数
  3. 机器学习之数学基础(四)~Lasso Regression回归, L1、L2 Regularization正则化, 回归问题中的损失函数
  4. python简笔画绘制 数据驱动绘图恐龙_使用python turtle绘制简笔画大白-Go语言中文社区...
  5. mybatis自动扫描注解
  6. 用BlazeMeter录制JMeter测试脚本
  7. Ubuntu16.04(64位)下安装和破解source insight4
  8. ant design 分页中文字_给你代码:ant-desgin-vue使用
  9. python列表生成多个号码_python遍历多个列表生成列表或字典
  10. python爬虫第二课:url解析
  11. Oracle修改SID(实例名)
  12. Oracle 20c 新特性详解:SQL Macro 宏 SCALAR / TABLE 模式带来的敏捷和便利
  13. JS魔法堂:那些困扰你的DOM集合类型
  14. python自动化办公-简直出神入化,教你用Python控制Excel实现自动化办公
  15. 小程序navigator点击有时候会闪一下
  16. Java编程:爬楼梯问题、斐波那契数列问题
  17. cad缩放_mac有没有好用的cad看图软件?CAD迷你看图 for Mac4.4.1激活版分享给大家...
  18. 接口性能测试方案分析
  19. 大一python选择题题库及答案_python选择题库
  20. paypal支付对接(付款方式:即时付款、快速付款):PC端支付、APP端支付,异步回调IPN

热门文章

  1. epoll监听文件_怎么理解把标准输入以ET模式加入epoll,监听EPOLLOUT事件时,epoll_wait多次返回?...
  2. 使用Python、OpenCV计算轮廓的中心
  3. CS131-专题7:图像特征(SIFT算法)
  4. 优达学城《DeepLearning》2-2:迁移学习
  5. Linux那些事儿 之 戏说USB(29)驱动的生命线(一)
  6. gym102443 D.Guess the Path
  7. 基于简化点云地图的语义边缘对齐的单目定位方法
  8. 设置WebStorm用Ctrl+鼠标滚轮上、下调整编辑器代码字体大小
  9. 使用Go语言遇到的“坑”收集
  10. 一文带你看透 GDB 的 实现原理 -- ptrace真香