一种清除windows通知区域“僵尸”图标的方案——Windows7系统解决方案
Windows7下“僵尸”圖標(biāo)的解決方案
? ? ? ??從《一種清除windows通知區(qū)域“僵尸”圖標(biāo)的方案——問題分析》(以后簡(jiǎn)稱《問題分析》)一文中分析的通知區(qū)域結(jié)構(gòu)可以看出,Windows7的通知區(qū)域比XP通知區(qū)域多出了一個(gè)“臨時(shí)”系統(tǒng)通知區(qū)域(轉(zhuǎn)載請(qǐng)指明出于breaksoftware的csdn博客)
? ? ? ? 雖然我們可以在“控制面板\所有控制面板項(xiàng)\通知區(qū)域圖標(biāo)”下選擇“始終在任務(wù)欄上顯示所有圖標(biāo)和通知(A)”,來讓W(xué)indows7的通知區(qū)域和XP上一致,但是我們無法讓用戶這么去做,因?yàn)槲覀兘o不出這樣做的必要。
? ? ? ? 這個(gè)隱藏的通知區(qū)域是讓我非常頭疼的,《一種清除windows通知區(qū)域“僵尸”圖標(biāo)的方案——XP系統(tǒng)解決方案》一文中的所有方案都不適用于它。
? ? ? ? 在各種方法走不通的情況下,我們不妨換一種思路:保證只有一個(gè)圖標(biāo)。如果進(jìn)程意外退出,那么在下次啟動(dòng)時(shí),再次注冊(cè)和新增通知區(qū)域圖標(biāo)時(shí),我們先刪掉原來的圖標(biāo)然后再新增圖標(biāo),而不是簡(jiǎn)單的新增一個(gè)圖標(biāo)。或許有人會(huì)問,為什么XP下不這么做呢?因?yàn)閄P下無法刪除其他進(jìn)程創(chuàng)建的圖標(biāo)。
? ? ? ?XP下密集出現(xiàn)的“僵尸”圖標(biāo)問題,應(yīng)該是引起了微軟的注意。所以他們?cè)赩ista之后的系統(tǒng)中,給通知區(qū)域圖標(biāo)新增了一個(gè)GUID信息。于是,我們就可以簡(jiǎn)單的指定GUID便可以保證了圖標(biāo)的唯一性!
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;
? ? ? ? 看似這個(gè)問題就這么解決了,但是問題絕對(duì)不是這么簡(jiǎn)單的。我們發(fā)現(xiàn),如果我們將程序A拷貝到其他目錄下叫作A‘。如果A'創(chuàng)建了圖標(biāo),并且A'進(jìn)程被殺死。那么A進(jìn)程可能出現(xiàn)無法創(chuàng)建和無法刪除圖標(biāo)的情況,這樣就嚴(yán)重影響了正常執(zhí)行流程。
? ? ? ? 其實(shí)這個(gè)問題也比較好解決:去掉hWnd參數(shù)的指定。但是這個(gè)方案將導(dǎo)致一個(gè)缺陷:通知區(qū)域圖標(biāo)不能將消息傳遞給主界面!
? ? ? ? 一個(gè)比較好的解決方法,就是讓不同目錄下進(jìn)程新增的圖標(biāo)的GUID不同。于是我們可以計(jì)算當(dāng)前進(jìn)程路徑的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));
……}? ? ? ? 創(chuàng)建圖標(biāo)的方法是
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下的圖標(biāo)問題也就解決了。這兒再記錄一份使用advapi.dll中相關(guān)方法計(jì)算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;}
? ? ? ? 最后附上工程地址
總結(jié)
以上是生活随笔為你收集整理的一种清除windows通知区域“僵尸”图标的方案——Windows7系统解决方案的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一种清除windows通知区域“僵尸”图
- 下一篇: 一种将快捷方式从开始菜单“常用应用”的中