前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一种清除windows通知区域“僵尸”图标的方案——Windows7系统解决方案

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

作者头像
方亮
发布2019-01-16 11:02:05
6800
发布2019-01-16 11:02:05
举报
文章被收录于专栏:方亮方亮

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

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

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

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

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

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

代码语言:javascript
复制
    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,方法是

代码语言:javascript
复制
……
    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));
……
    }

        创建图标的方法是

代码语言:javascript
复制
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的代码

代码语言:javascript
复制
#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;

}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2013年12月09日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Windows7下“僵尸”图标的解决方案
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档