一种清除windows通知区域“僵尸”图标的方案——Windows7系统解决方案
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系统解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一种清除windows通知区域“僵尸”图
- 下一篇: 一种将快捷方式从开始菜单“常用应用”的中