Link to home
Start Free TrialLog in
Avatar of fuzorblade64
fuzorblade64

asked on

Shell_NotifyIcon returns FALSE

Hi,

I have an application that runs as a Windows service and shows up in system tray. I am compiling the application in XP SP1 and everything works fine on XP. When I install this same exe on Windows 2000 server machine and the service is started, the exe runs but it never shows up in the system tray. I added some debug code and it seems that GetLastError after Shell_NotifyIcon is returning error 2, which is 'system cannot find the specified file'. Also when the same exe on Windows 2000 machine is run as a normal application (by double clicking), it appears fine in system tray. The service is set up to interact with the desktop.

Here is the code that adds the icon to system tray and it always returns false when run as service on W2K.

BOOL TaskBarAddIcon (HWND hWnd, UINT uID)
{
    BOOL bRet;
    NOTIFYICONDATA tnid;
    HANDLE hIcon = NULL;

    gCurrID = uID;
    hIcon = LoadIcon (hInst, MAKEINTRESOURCE (uID));
    tnid.cbSize = sizeof (NOTIFYICONDATA);
    tnid.hIcon = hIcon;
    tnid.hWnd = hWnd;
    lstrcpy (tnid.szTip, "My tip");
    tnid.uCallbackMessage = MY_TASK;
    tnid.uID = uID;
    tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
    bRet = Shell_NotifyIcon (NIM_ADD, &tnid);
    if (hIcon) DestroyIcon (hIcon);
    return (bRet);
}

Do you have any suggestions?

fuzorblade64
Avatar of jkr
jkr
Flag of Germany image

Are 'hIcon' and/or 'hInst' valid?
Avatar of fuzorblade64
fuzorblade64

ASKER

Yes, both hIcon and hWnd are non-null.
>>I have an application that runs as a Windows service and shows up in system tray.

If your service application loads up before a user logs on, there's no place to put the icon.
To get your service to work with the trayicon, you should use a secondary application that starts up after a loggon.

You can then interface between the secondary and service application to display menu's and activate options.
Well, I am already logged on to the machine and I start the service manually. In this case it should show up.
>>Well, I am already logged on to the machine and I start the service manually. In this case it should show up.

I've tried this before myself, and it does not show up.
My application was also able to display the trayicon when I launched it directly, but when it launch via service mode, it also failed on Shell_NotifyIcon.

I didn't investigate any further, because I realize even if I some how got it to work while I was logged on, it would fail on reboot.

Do you need this to work on reboot?

If so, Shell_NotifyIcon will always fail on reboot for a service application.
The icon only matters when a user is logged in. So as long as it shows up in the system tray after a user logs in, I am fine. For this, I have a timer, which checks for the presence of the icon (by trying to modify it) and if it is not found, it adds it.
I also want to emphasize that this works perfectly on Windows XP, SP1 and SP2.
>>I also want to emphasize that this works perfectly on Windows XP, SP1 and SP2.

I have you tested it out on reboot for XP?
Yes, I have been using it on XP for a few weeks now. Every time I reboot and login, I see the icon in system tray because of that timer code mentioned earlier. Before I added that code, if I logged out and logged back in the icon used to be gone.
Check out the following link:
http://www.codeproject.com/shell/systemtray.asp?df=100

The above link claims that the CSystemTray class can work with service application and with Windows 2000.

I looked at some of the code, and I notice the code has Win2K specific logic, however you need the latest SDK loaded on your development computer in order to compile the code.

In the latest SDK the ShellAPI.h header has additional data members for NOTIFYICONDATA.

typedef struct _NOTIFYICONDATAA {
        DWORD cbSize;
        HWND hWnd;
        UINT uID;
        UINT uFlags;
        UINT uCallbackMessage;
        HICON hIcon;
#if (_WIN32_IE < 0x0500)
        CHAR   szTip[64];
#else
        CHAR   szTip[128];
#endif
#if (_WIN32_IE >= 0x0500)
        DWORD dwState;
        DWORD dwStateMask;
        CHAR   szInfo[256];
        union {
            UINT  uTimeout;
            UINT  uVersion;
        } DUMMYUNIONNAME;
        CHAR   szInfoTitle[64];
        DWORD dwInfoFlags;
#endif
#if (_WIN32_IE >= 0x600)
        GUID guidItem;
#endif
} NOTIFYICONDATAA, *PNOTIFYICONDATAA;

The CSystemTray class makes modifications to these additional data members.
FYI:
I just tried compileing above code at my current work site (which does NOT have the latest SDK), and it compiles, but without the W2K specific code logic.

The following macro in the above code will stop the W2K code logic from compiling if you don't have the latest SDK installed.

#ifdef NOTIFYICONDATA_V1_SIZE   // If NOTIFYICONDATA_V1_SIZE, then we can use fun stuff
#define SYSTEMTRAY_USEW2K
#else
#define NIIF_NONE 0
#endif
I just compiled TaskBardemo and installed it as service on W2K (with the help of srvany.exe and instsrv.exe) and it does not show up in the system tray.
ASKER CERTIFIED SOLUTION
Avatar of Axter
Axter
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
OK, I think an apology is in order. After I got too frustrated, I decided to log in as console user as opposed to remote desktop session and Voila! the icon shows up. This behavior is different from XP, where I have been logging thru remote desktop and icon always shows up properly.

I am extremely sorry for all the wasted cycles I have caused.
>>I am extremely sorry for all the wasted cycles I have caused.

Does it work with your old code, or only with the TaskBardemo code?
The old code works. One more point to clarify, it could be the server issue also. XP pro was working thru RDC and Windows Server 2000 was not. I haven't tried server 2003 or Windows 2000 pro. So it could be the difference between W2K and XP or server and professional version.
My target test platform is Windows 2000 Advance Server, and my original code does not work on it.

I haven't tried using TaskBardemo's code because I don't have the latest SDK on my client's development machine.
Does anybody know why the icon does not appear when connecting to W2K server thru terminal service. I see some of the icons in system tray even when I go into the server thru terminal service but not mine. What is required to be done for the icon to appear in all cases?
Okay, please close the question. My problem is not resolved though.
>>Okay, please close the question. My problem is not resolved though.
I was under the impression, that your main question was answered, and that your problem was related to logging on via terminal server.