2012年4月2日 星期一

Shell_NotifyIcon Fails with ERROR_NO_TOKEN

要新增一個 tray icon 時, 我們會呼叫 Shell_NotifyIcon(), 但不知為什麼, 偶爾會失敗, 而且更慘的是都在客戶的機器上發生, 從網上討論區中也發現其他人也有遇到這種情況, 也看到了一些解決方案, 譬如在 NIM_ADD 失敗後, 就先 NIM_DELETE 再重試, 也的確有效, 就這樣撐了好幾年.

最近在某客戶的 Windows 7 機器上又發生了無法新增 tray icon 的情況, 而且是所有應用程式的 tray icon 都無法顯示, 複製此現象的步驟著實詭異:
  1. 在進作業系統前, 先進 BIOS Setup, 將系統日期的年改一下, 改成什麼都好, 只要有改就好, 改完後儲存, 進作業系統.
  2. 進作業系統後, 會發現應用程式的 tray icon 都消失了(新增失敗).
  3. 重開機後又正常了, 只有改完系統日期後的第一次進作業系統會發生次現象, 因此可以再重複步驟 1~2 複製此現象.
研究之後, 發現在此現象發生時, NIM_ADD 都會失敗, 並且 GetLastError() 傳回 ERROR_NO_TOKEN, 系統還會頓一下. 同樣地先拜了 google 大神, 但這次不靈了, 沒多少資訊是值得參考的, 只好自己下海找解決辦法, 也很幸運地, 找到了解法, 只要在 NIM_ADD 失敗後, 如果 GetLastError() 傳回 ERROR_NO_TOKEN, 就以 NIM_MODIFY 重試即可, 新舊解法合在一起用, 大致如下:
NOTIFYICONDATA nid;

/* TODO: initialize nid */

if (Shell_NotifyIcon(NIM_ADD, &nid) == FALSE)
{
        if (GetLastError() == ERROR_NO_TOKEN)
        {
                if (Shell_NotifyIcon(NIM_MODIFY, &nid) == TRUE)
                {
                        /* successful */
                        return;
                }
        }

        Sleep(500);
        Shell_NotifyIcon(NIM_DELETE, &nid);
}


更多資訊:
- The trouble with Shell_NotifyIcon()



沒有留言:

張貼留言