Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 894
  • Last Modified:

Shell_NotifyIcon fails with ERROR_FILE_NOT_FOUND on Vista Beta II

Hi all. We are in the process of testing our application on Windows Vista Beta II to find portability issues. The program is a Windows Service that runs with the System Account user and has access to the desktop. When the service tries to install its icon in the Notification Area, the Shell_NotifyIcon function fails with ERROR_FILE_NOT_FOUND.

I know Vista has increased security compared to XP, and I'm pretty sure it has something to do with it. The only solution I came up with is to make another program that handles the tray messages and dispatches the commands to the service thru a named pipe. I would like to avoid this solution if possible.

Here's the code I use :

// test_tray.cpp
#include "stdafx.h"
#include "shellapi.h"
#include "resource.h"
#include "ntservice.h"
#include <misc/trace.h>

#define SERVICE_NAME                "CRAService"

using namespace TELUS::Angel::Misc;

bool  RegisterWindow();
void WINAPI Run(DWORD argc, char* argv[]);
HWND                              ghWnd = NULL;

NtService               gobjService;
UINT                              gMsg = 0;

void WINAPI Run(DWORD argc, char* argv[])
      NOTIFYICONDATA            mNiData = {0};
      bool                              isSuccess = false;

      TRACE_INIT_PROCESS("C:\\tray_tester.log", Trace::FullTrace);

   gobjService.setStatus(SERVICE_START_PENDING, 0, 30);

      gMsg = RegisterWindowMessage("AlsNotifyCommand");
      if (!gMsg)
      // Create the Msg Window
      if (isSuccess = RegisterWindow())
            ghWnd = CreateWindow("AlsMsgWndClass", "", WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
            isSuccess = ghWnd != NULL;
            if (!isSuccess)
      // Add Tray Icon
      if (isSuccess)
            mNiData.cbSize = sizeof(NOTIFYICONDATA);
            mNiData.uID = IDI_NOTIFY_ICON;
            mNiData.uFlags = NIF_ICON|NIF_MESSAGE|NIF_TIP;
            mNiData.hIcon =
                  (HICON)LoadImage( GetModuleHandle(NULL),

            if (!mNiData.hIcon)
            strcpy(mNiData.szTip, "test tip");
            mNiData.hWnd = ghWnd;
            mNiData.uCallbackMessage = gMsg;

            if (!Shell_NotifyIcon(NIM_ADD, &mNiData))
                  DWORD dw = GetLastError();
                  TRACE_ERROR("Could not display ICON");
                  TRACE_SYS_CALL_CODE("Shell_NotifyIcon", dw);

      MSG msg;
      while (GetMessage(&msg, NULL, 0, 0))

LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
      int wmId, wmEvent;
      HMENU gMenu, gSubMenu;
      NOTIFYICONDATA            mNiData = {0};

      if (message == gMsg)
            if (lParam == WM_RBUTTONUP)
                  POINT pos = {0};
                  gMenu = LoadMenu(GetModuleHandle(NULL), MAKEINTRESOURCE(ID_MENU_ICON));

                        gSubMenu = GetSubMenu(gMenu, 0);

                        TrackPopupMenu(gSubMenu, TPM_RIGHTALIGN, pos.x, pos.y, 0, ghWnd, NULL);
      else if (message == WM_COMMAND)
            wmId    = LOWORD(wParam);
            wmEvent = HIWORD(wParam);
            // Analyse les sĂ©lections de menu :
            switch (wmId)
            case ID_POPUP_2:
                  mNiData.cbSize = sizeof(NOTIFYICONDATA);
                  mNiData.uID = IDI_NOTIFY_ICON;
                  mNiData.hWnd = ghWnd;
                  Shell_NotifyIcon(NIM_DELETE, &mNiData);
                  return DefWindowProc(hWnd, message, wParam, lParam);
      else if (message == WM_DESTROY)
            return DefWindowProc(hWnd, message, wParam, lParam);

      return 0;

bool RegisterWindow()
      bool isSuccess = false;

      WNDCLASSEX wcx = {0};

      wcx.style                  = CS_HREDRAW | CS_VREDRAW;
   wcx.cbSize = sizeof(wcx);          // size of structure
   wcx.lpfnWndProc = MainWndProc;     // points to window procedure
   wcx.hInstance = GetModuleHandle(NULL);
   wcx.hIcon = NULL;
   wcx.hCursor = NULL;
   wcx.lpszClassName = "AlsMsgWndClass";  // name of window class

   isSuccess = RegisterClassEx(&wcx) != 0;

      if (!isSuccess)

      TRACE_END_RET(isSuccess, isSuccess);
      return isSuccess;

int main(int argc, char* argv[])
      NtService::startDispatcher(SERVICE_NAME, Run);
      return 0;
1 Solution
This is because in Vista, Services run in a different session to conventional applications, so they have no access to the desktop or any of it's components. Most, if not all conventional UI calls will fail.

Have a look at:

This contains a description of what's happening together with some possible workarounds.



Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now