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

System Tray Enumeration

Is there a way to enumerate all the icons on the system tray? I would like to be able to find out the IDs for all of the icons on the tray, but there doesn't appear to be an API to do it.

Thanks in advance.
0
eppsman
Asked:
eppsman
  • 9
  • 5
  • 2
  • +1
1 Solution
 
alexoCommented:
There isn't any documented way of doing it.

However, see if these can help:
    http://www.dejanews.com/getdoc.xp?AN=217891054
    http://www.dejanews.com/getdoc.xp?AN=329990694

0
 
eppsmanAuthor Commented:
Thanks, that did give me an idea for a starting point. I've decided to try to tackle the problem from a different angle. I was able to force a DLL that I wrote into explorer's address space, and subclass the system tray. I can now see any WM_COPYDATA messages that are sent via Shell_NotifyIcon(). The problem is, when I go to examine the data as a NOTIFYICONDATA structure, all I can get is garbage that holds the same value every time - even in different Windows sessions. I disassembled Shell_NotifyIcon(), and it looks like it fudges with the NOTIFYICONDATA structure before sending the WM_COPYDATA message. Unfortunately, I am not fluent enough in assembly to be able to figure out what Shell_NotifyIcon() is doing. Does anybody know what is going on?

Thanks in advance.
0
 
alexoCommented:
Sorry, no idea.
0
Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

 
eppsmanAuthor Commented:
Adjusted points to 400
0
 
eppsmanAuthor Commented:
Adjusted points to 1000
0
 
NickRepinCommented:
eppsman, the cost of you Q is very interesting, so may be I can help you.
At first, what exactly do you want:
   1) Hook to the explorer at boot time and intercept icon calls to save icon info. It seems that this is more easy than 2)
or,
   2) Run your program at any time to enumerate icon (this may be impossible at all, at least, without 1)

Next, I'm fluent in asm, so you can post to me asm code along with information you discovered (WM_COPYDATA, and the source to sublassing tray window). My email is nick@rtzi.ru.
It can take about 2-3 day to see what can be done.
 
0
 
NickRepinCommented:
I've made a little investigation into the Shell_NotifyIcon code.
I can offer to you (for grade A) following solution (w/source code):

  1)Hook to the explorer
  2)After hooking, you will be able to intercept the all calls to the  Shell_NotifyIcon.

  If you agree, post a comment.
  Also, to save time, you may post to me the code to sublass the system tray (see address in comments above).


0
 
eppsmanAuthor Commented:
Nick,

Sounds good! I'll send you my code for subclassing when I get home later today.
0
 
NickRepinCommented:
eppsman, I've received, but never seen your email yet. Nevertheless, here is the answer.
Ask me if you have any questions.

In the following comments see the source code of the Shell_NotifyIcon.

I suggest you to do the following.

Write app and run it BEFORE the explorer starts.

In app, create system-wide hook (eg,WH_CBT) to check when the
SystemTrayWindow will be created (class name "Shell_TrayWnd").
Store the handle of this window.

Next, you may either subclass this window, or install another system hook to monitor messages to this window (eg, WH_CALLWNDPROCRET).

In the subclass proc (hook), do the following (for constant values, see my source code in comments):

   ... WndProc(HWND hWnd,UINT uMsg,WPARAM wP,LPARAM lP);
  if(hWnd==hSystemTrayWnd && uMsg==WM_COPYDATA) {
     // Check if NotifyIcon call
     COPYDATASTRUCT* cd =(COPYDATASTRUCT) lp;
     if(cd->dwData==NOTIFY_ICON_CALL && cd->cbData>=sizeof(MsgDataT) && cd->lpData!=0) {
         MsgDataT* d=(MsgDataT*) (cd->lpData);
         if(d->magicN==MAGICN) {
            // Ok, this is the right message
            // here call the old window proc and check if return code is successful.
            if(oldProc(....)) {
               NOTIFYICONDATA data=d->d;

               // Here we can save the data!
            }
         }
   }
}

Also, in comments below I've posted the console app that enumerates icons info at any time, without any hook. But there is a problem in it. Its because the Windows saves icon handle in ImageList control. And we cannot (at least, I don't know how to do it now) call ImageList_xxx() functions with HIMAGELIST
obtained from an another app.

In any case, I think I've earned grade A. I've lost on this about half of the day.

I'll make some efforts to force imagelist to work.
 
0
 
NickRepinCommented:
// Source code for Shell_NotifyIcon - Windows 95
//

#include <windows.h>
#include <commctrl.h>
#include <iostream.h>
#include <stdlib.h>

struct MsgDataT {
   DWORD magicN;
   DWORD msg;
   NOTIFYICONDATA d;
};
#define MAGICN 0x34753423
#define NOTIFY_ICON_CALL 1

//-----------------------------------------
WINSHELLAPI BOOL WINAPI _Shell_NotifyIcon(DWORD dwMessage,
   PNOTIFYICONDATA pnid)
{
   HWND tray=FindWindow("Shell_TrayWnd",0);
   if(!tray) return 0;
   MsgDataT data;
   data.magicN=MAGICN;
   data.msg=dwMessage;
   data.d=*pnid;
   data.d.uFlags&=7;

   COPYDATASTRUCT cd;
   cd.dwData=NOTIFY_ICON_CALL;
   cd.cbData=sizeof(MsgDataT);
   cd.lpData=&data;

   return SendMessage(tray,WM_COPYDATA,WPARAM(pnid->hWnd),LPARAM(&cd));
}

0
 
NickRepinCommented:
I've tired to wait while exeprts-exchange processes my comments.
So all of the code (4 files) is here
**********************************************************************
**********************************************************************
// Source code for Shell_NotifyIcon - Windows 95
//

#include <windows.h>
#include <commctrl.h>
#include <iostream.h>
#include <stdlib.h>

struct MsgDataT {
   DWORD magicN;
   DWORD msg;
   NOTIFYICONDATA d;
};
#define MAGICN 0x34753423
#define NOTIFY_ICON_CALL 1

//-----------------------------------------
WINSHELLAPI BOOL WINAPI _Shell_NotifyIcon(DWORD dwMessage,
   PNOTIFYICONDATA pnid)
{
   HWND tray=FindWindow("Shell_TrayWnd",0);
   if(!tray) return 0;
   MsgDataT data;
   data.magicN=MAGICN;
   data.msg=dwMessage;
   data.d=*pnid;
   data.d.uFlags&=7;

   COPYDATASTRUCT cd;
   cd.dwData=NOTIFY_ICON_CALL;
   cd.cbData=sizeof(MsgDataT);
   cd.lpData=&data;

   return SendMessage(tray,WM_COPYDATA,WPARAM(pnid->hWnd),LPARAM(&cd));
}
**********************************************************************
**********************************************************************
// Source code for Shell_NotifyIcon - Windows NT
//

#include <windows.h>
#include <commctrl.h>
#include <iostream.h>
#include <stdlib.h>

struct MsgDataT {
   DWORD magicN;
   DWORD msg;
   NOTIFYICONDATAW d;
};
#define MAGICN 0x34753423;
#define NOTIFY_ICON_CALL 1

//-----------------------------------------
WINSHELLAPI BOOL WINAPI _Shell_NotifyIconW(DWORD dwMessage,
   PNOTIFYICONDATAW pnid)
{
   wchar_t* clsName=L"Shell_TrayWnd";
   HWND tray=FindWindowW(clsName,0);
   if(!tray) return 0;
   MsgDataT data;
   data.magicN=MAGICN;
   data.msg=dwMessage;
   data.d=*pnid;
   data.d.uFlags&=7;

   COPYDATASTRUCT cd;
   cd.dwData=NOTIFY_ICON_CALL;
   cd.cbData=sizeof(MsgDataT);
   cd.lpData=&data;

   return SendMessageW(tray,WM_COPYDATA,WPARAM(pnid->hWnd),LPARAM(&cd));
}
//-----------------------------------------
WINSHELLAPI BOOL WINAPI _Shell_NotifyIconA(DWORD dwMessage,
   PNOTIFYICONDATAA pnid)
{
   NOTIFYICONDATAW d;
   d.hWnd=pnid->hWnd;
   d.uID=pnid->uID;
   d.uFlags=pnid->uFlags;
   d.uCallbackMessage=pnid->uCallbackMessage;
   d.hIcon=pnid->hIcon;

   MultiByteToWideChar(CP_ACP,0,pnid->szTip,sizeof(pnid->szTip),
      d.szTip,sizeof(d.szTip)/2);

   return Shell_NotifyIconW(dwMessage,&d);
}
**********************************************************************
**********************************************************************
//   Enumerate systray icons - Windows 95
//
#include <windows.h>
#include <commctrl.h>
#include <iostream.h>
#include <stdlib.h>

struct TWIconDataT {
   DWORD internalId
0
 
NickRepinCommented:
I've tired to wait while exeprts-exchange processes my comments.
So all of the code (4 files) is here
**********************************************************************
**********************************************************************
// Source code for Shell_NotifyIcon - Windows 95
//

#include <windows.h>
#include <commctrl.h>
#include <iostream.h>
#include <stdlib.h>

struct MsgDataT {
   DWORD magicN;
   DWORD msg;
   NOTIFYICONDATA d;
};
#define MAGICN 0x34753423
#define NOTIFY_ICON_CALL 1

//-----------------------------------------
WINSHELLAPI BOOL WINAPI _Shell_NotifyIcon(DWORD dwMessage,
   PNOTIFYICONDATA pnid)
{
   HWND tray=FindWindow("Shell_TrayWnd",0);
   if(!tray) return 0;
   MsgDataT data;
   data.magicN=MAGICN;
   data.msg=dwMessage;
   data.d=*pnid;
   data.d.uFlags&=7;

   COPYDATASTRUCT cd;
   cd.dwData=NOTIFY_ICON_CALL;
   cd.cbData=sizeof(MsgDataT);
   cd.lpData=&data;

   return SendMessage(tray,WM_COPYDATA,WPARAM(pnid->hWnd),LPARAM(&cd));
}
**********************************************************************
**********************************************************************
// Source code for Shell_NotifyIcon - Windows NT
//

#include <windows.h>
#include <commctrl.h>
#include <iostream.h>
#include <stdlib.h>

struct MsgDataT {
   DWORD magicN;
   DWORD msg;
   NOTIFYICONDATAW d;
};
#define MAGICN 0x34753423;
#define NOTIFY_ICON_CALL 1

//-----------------------------------------
WINSHELLAPI BOOL WINAPI _Shell_NotifyIconW(DWORD dwMessage,
   PNOTIFYICONDATAW pnid)
{
   wchar_t* clsName=L"Shell_TrayWnd";
   HWND tray=FindWindowW(clsName,0);
   if(!tray) return 0;
   MsgDataT data;
   data.magicN=MAGICN;
   data.msg=dwMessage;
   data.d=*pnid;
   data.d.uFlags&=7;

   COPYDATASTRUCT cd;
   cd.dwData=NOTIFY_ICON_CALL;
   cd.cbData=sizeof(MsgDataT);
   cd.lpData=&data;

   return SendMessageW(tray,WM_COPYDATA,WPARAM(pnid->hWnd),LPARAM(&cd));
}
//-----------------------------------------
WINSHELLAPI BOOL WINAPI _Shell_NotifyIconA(DWORD dwMessage,
   PNOTIFYICONDATAA pnid)
{
   NOTIFYICONDATAW d;
   d.hWnd=pnid->hWnd;
   d.uID=pnid->uID;
   d.uFlags=pnid->uFlags;
   d.uCallbackMessage=pnid->uCallbackMessage;
   d.hIcon=pnid->hIcon;

   MultiByteToWideChar(CP_ACP,0,pnid->szTip,sizeof(pnid->szTip),
      d.szTip,sizeof(d.szTip)/2);

   return Shell_NotifyIconW(dwMessage,&d);
}
**********************************************************************
**********************************************************************
//   Enumerate systray icons - Windows 95
//
#include <windows.h>
#include <commctrl.h>
#include <iostream.h>
#include <stdlib.h>

struct TWIconDataT {
   DWORD internalId;  // image index, -1 if no image in iconList
   NOTIFYICONDATA d;
};

typedef TWIconDataT* pTWIconDataT;

struct TWIconsInfoT {
   int Cnt;
   pTWIconDataT* iconData;
};

struct TWDataT {
   DWORD unknown[7];
   TWIconsInfoT* iconsInfo;
   HIMAGELIST    iconList;
};

void main(void)
{
   InitCommonControls();

   HWND stw=FindWindow("Shell_TrayWnd",0);
   if(!stw) {
      cout<<"System tray not found!"<<endl;
      return;
   }

   HWND tw=FindWindowEx(stw,0,"TrayNotifyWnd",0);
   if(!tw) {
      cout<<"TrayNotifyWnd not found!"<<endl;
      return;
   }
   TWDataT* twd=(TWDataT*)GetWindowLong(tw,0);
   if(!twd) {
      cout<<"Cannot get TrayNotifyWnd data! "<<GetLastError()<<endl;
      return;
   }

   // We cannot just read memory of another process

   DWORD idExplorer;
   GetWindowThreadProcessId(tw,&idExplorer);
   HANDLE hExplorer=OpenProcess(PROCESS_VM_READ,FALSE,idExplorer);
   if(!hExplorer) {
      cout<<"Cannot open Explorer process! "<<GetLastError()<<endl;
      return;
   }

   //Read tray window data
   TWDataT data;
   BOOL r=ReadProcessMemory(hExplorer,twd,&data,sizeof(data),0);
   if(!r) {
      cout<<"Cannot read tray window data! "<<GetLastError()<<endl;
      return;
   }

   cout<<"Image list="<<data.iconList<<endl;

   // Read icons info
   TWIconsInfoT iconsInfo;
   r=ReadProcessMemory(hExplorer,data.iconsInfo,&iconsInfo,
      sizeof(iconsInfo),0);
   if(!r) {
      cout<<"Cannot read icons info! "<<GetLastError()<<endl;
      return;
   }

   if(iconsInfo.Cnt==0) {
      cout<<"No tray icons!"<<endl;
      return;
   }
   else cout<<"Icons count="<<(iconsInfo.Cnt)<<endl;

   // Ok, now read pointers to icons data
   pTWIconDataT* ppIconData=new pTWIconDataT[iconsInfo.Cnt];
   r=ReadProcessMemory(hExplorer,iconsInfo.iconData,ppIconData,
      sizeof(pTWIconDataT)*iconsInfo.Cnt,0);
   if(!r) {
      cout<<"Cannot read pointers to icons data! "<<GetLastError()<<endl;
      return;
   }

   // Now read icons data itself
   pTWIconDataT pIconData=new TWIconDataT[iconsInfo.Cnt];
   for(int i=0;i<iconsInfo.Cnt;i++) {
      r=ReadProcessMemory(hExplorer,ppIconData[i],pIconData+i,
         sizeof(TWIconDataT),0);
      if(!r) {
         cout<<"Cannot read icon data #"<<i<<"! "<<GetLastError()<<endl;
         return;
      }
   }

   delete[] ppIconData;
   CloseHandle(hExplorer);

   // Now, add points to Nick's account for wasted 4 hour!!

   for(int i=iconsInfo.Cnt-1;i>=0;i--) {
      cout<<endl<<"# "<<i<<" *****************"<<endl;
      cout<<"internalId="<<(pIconData[i].internalId)<<endl;
      cout<<"hWnd="<<(pIconData[i].d.hWnd)<<endl;
      cout<<"uID="<<(pIconData[i].d.uID)<<endl;
      cout<<"uFlags="<<(pIconData[i].d.uFlags)<<endl;
      cout<<"uCallbackMessage="<<(pIconData[i].d.uCallbackMessage)<<endl;
      cout<<"hIcon="<<(pIconData[i].d.hIcon)<<endl;
      cout<<"szTip="<<(pIconData[i].d.szTip)<<endl;
      // Will not work
      //HICON icon=ImageList_GetIcon(data.iconList,pIconData[i].internalId,
      //   ILD_NORMAL);
      //cout<<"Real icon="<<icon<<endl;
   }

   delete[] pIconData;
}
**********************************************************************
**********************************************************************
//  Enumerate system tray icons - Windows NT
//
#include <windows.h>
#include <commctrl.h>
#include <iostream.h>
#include <stdlib.h>

struct TWIconDataT {
   DWORD internalId;  // image index, -1 if no image in iconList
   NOTIFYICONDATAW d;
};

typedef TWIconDataT* pTWIconDataT;

struct TWIconsInfoT {
   int Cnt;
   pTWIconDataT* iconData;
};

struct TWDataT {
   DWORD unknown[7];
   TWIconsInfoT* iconsInfo;
   HIMAGELIST    iconList;
};

void main(void)
{
   InitCommonControls();

   HWND stw=FindWindow("Shell_TrayWnd",0);
   if(!stw) {
      cout<<"System tray not found!"<<endl;
      return;
   }

   HWND tw=FindWindowEx(stw,0,"TrayNotifyWnd",0);
   if(!tw) {
      cout<<"TrayNotifyWnd not found!"<<endl;
      return;
   }
   TWDataT* twd=(TWDataT*)GetWindowLong(tw,0);
   if(!twd) {
      cout<<"Cannot get TrayNotifyWnd data! "<<GetLastError()<<endl;
      return;
   }

   // We cannot just read memory of another process

   DWORD idExplorer;
   GetWindowThreadProcessId(tw,&idExplorer);
   HANDLE hExplorer=OpenProcess(PROCESS_VM_READ,FALSE,idExplorer);
   if(!hExplorer) {
      cout<<"Cannot open Explorer process! "<<GetLastError()<<endl;
      return;
   }

   //Read tray window data
   TWDataT data;
   BOOL r=ReadProcessMemory(hExplorer,twd,&data,sizeof(data),0);
   if(!r) {
      cout<<"Cannot read tray window data! "<<GetLastError()<<endl;
      return;
   }

   cout<<"Image list="<<data.iconList<<endl;

   // Read icons info
   TWIconsInfoT iconsInfo;
   r=ReadProcessMemory(hExplorer,data.iconsInfo,&iconsInfo,
      sizeof(iconsInfo),0);
   if(!r) {
      cout<<"Cannot read icons info! "<<GetLastError()<<endl;
      return;
   }

   if(iconsInfo.Cnt==0) {
      cout<<"No tray icons!"<<endl;
      return;
   }
   else cout<<"Icons count="<<(iconsInfo.Cnt)<<endl;

   // Ok, now read pointers to icons data
   pTWIconDataT* ppIconData=new pTWIconDataT[iconsInfo.Cnt];
   r=ReadProcessMemory(hExplorer,iconsInfo.iconData,ppIconData,
      sizeof(pTWIconDataT)*iconsInfo.Cnt,0);
   if(!r) {
      cout<<"Cannot read pointers to icons data! "<<GetLastError()<<endl;
      return;
   }

   // Now read icons data itself
   pTWIconDataT pIconData=new TWIconDataT[iconsInfo.Cnt];
   for(int i=0;i<iconsInfo.Cnt;i++) {
      r=ReadProcessMemory(hExplorer,ppIconData[i],pIconData+i,
         sizeof(TWIconDataT),0);
      if(!r) {
         cout<<"Cannot read icon data #"<<i<<"! "<<GetLastError()<<endl;
         return;
      }
   }

   delete[] ppIconData;
   CloseHandle(hExplorer);

   // Now, add points to Nick's account for wasted 4 hour!!

   for(int i=iconsInfo.Cnt-1;i>=0;i--) {
      cout<<endl<<"# "<<i<<" *****************"<<endl;
      cout<<"internalId="<<(pIconData[i].internalId)<<endl;
      cout<<"hWnd="<<(pIconData[i].d.hWnd)<<endl;
      cout<<"uID="<<(pIconData[i].d.uID)<<endl;
      cout<<"uFlags="<<(pIconData[i].d.uFlags)<<endl;
      cout<<"uCallbackMessage="<<(pIconData[i].d.uCallbackMessage)<<endl;
      cout<<"hIcon="<<(pIconData[i].d.hIcon)<<endl;
      char buf[64];
      wcstombs(buf,pIconData[i].d.szTip,sizeof(buf));
      cout<<"szTip="<<buf<<endl;
      // Will not work
      //HICON icon=ImageList_GetIcon(data.iconList,pIconData[i].internalId,
      //   ILD_NORMAL);
      //cout<<"Real icon="<<icon<<endl;
   }

   delete[] pIconData;
}

0
 
eppsmanAuthor Commented:
Great! This is just what I needed! Thanks for taking the time, you're right, it deserves an A. Thanks again.
0
 
NickRepinCommented:
Here is the full answer to your Q (w/ icon handles). It works for NT and 95 and more simple.


//***************************************************************
//  sh.cpp - Enumerate system tray icons - main module (console app).
//  Run it in window, not in the full-screen mode.
//
//  Creates the console, attached to the Explorer.
//  The icons info will be printed on this console.
//  Icons itself will be painted on the console window caption
//       at 200-pixels offset from the left.
//
//  Console automatically destroys after 10 sec.
//
//  Link with shdll.dll.
//
//***************************************************************
#define STRICT

#include <windows.h>
#include <iostream.h>
#include <conio.h>


void _import SetTrayHook();

void main(void)
{
   SetTrayHook();

   Sleep(15000);

   SetTrayHook();
}
//*******************************************
// File: shdll.cpp. Compile as DLL
//*******************************************
#define STRICT
#include <windows.h>
#include <commctrl.h>
#include <stdlib.h>

bool IsNT()
{
   OSVERSIONINFO v;
   v.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
   ::GetVersionEx(&v);
   return v.dwPlatformId==VER_PLATFORM_WIN32_NT;
}

bool isNT=IsNT();

void _export SetTrayHook();
void enumerateIcons();
void out(char* p=0);
LRESULT CALLBACK MsgProc(int,WPARAM,LPARAM);

HINSTANCE hInstance;
HHOOK hHook=0;
HWND SysTray=0;
HWND NotifyWnd=0;
DWORD dwExplorerThreadId=0,dwExplorerProcessId=0;

char msg[256];
HANDLE hCon=0;
HWND wCon=0;

BOOL WINAPI DllEntryPoint(HINSTANCE hInstDll,DWORD fdwReason,LPVOID)
{
   switch(fdwReason) {
   case DLL_PROCESS_ATTACH:
      hInstance=hInstDll;
      break;
   case DLL_THREAD_ATTACH:
      break;
   case DLL_PROCESS_DETACH:
      break;
   case DLL_THREAD_DETACH:
      break;
   }
   return TRUE;
}

void SetTrayHook()
{
   if(hHook==NULL) {
      SysTray=FindWindow("Shell_TrayWnd",NULL);
      NotifyWnd=FindWindowEx(SysTray,0,"TrayNotifyWnd",0);
      dwExplorerThreadId=GetWindowThreadProcessId(SysTray,
         &dwExplorerProcessId);
      hHook=SetWindowsHookEx(WH_CALLWNDPROC,HOOKPROC(MsgProc),
         hInstance,dwExplorerThreadId);
      //PostThreadMessage(dwExplorerThreadId,WM_NULL,0,0);
   }
   else {
      UnhookWindowsHookEx(hHook);
      hHook=NULL;
   }
   return;
}

bool isFirst=true;
LRESULT CALLBACK MsgProc(int nCode,WPARAM wParam,LPARAM lParam)
{
   if(isFirst) {
      isFirst=false;
      isNT=IsNT();
      SysTray=FindWindow("Shell_TrayWnd",NULL);
      NotifyWnd=FindWindowEx(SysTray,0,"TrayNotifyWnd",0);
      // To display messages
      AllocCo
0
 
NickRepinCommented:
Here is the full answer to your Q. It works for NT and 95 and more simple.


//***************************************************************
//  sh.cpp - Enumerate system tray icons - main module (console app).
//  Run it in window, not in the full-screen mode.
//
//  Creates the console, attached to the Explorer.
//  The icons info will be printed on this console.
//  Icons itself will be painted on the console window caption
//       at 200-pixels offset from the left.
//
//  Console automatically destroys after 10 sec.
//
//  Link with shdll.dll.
//
//***************************************************************
#define STRICT

#include <windows.h>
#include <iostream.h>
#include <conio.h>


void _import SetTrayHook();

void main(void)
{
   SetTrayHook();

   Sleep(15000);

   SetTrayHook();
}
//*******************************************
// File: shdll.cpp. Compile as DLL
//*******************************************
#define STRICT
#include <windows.h>
#include <commctrl.h>
#include <stdlib.h>

bool IsNT()
{
   OSVERSIONINFO v;
   v.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
   ::GetVersionEx(&v);
   return v.dwPlatformId==VER_PLATFORM_WIN32_NT;
}

bool isNT=IsNT();

void _export SetTrayHook();
void enumerateIcons();
void out(char* p=0);
LRESULT CALLBACK MsgProc(int,WPARAM,LPARAM);

HINSTANCE hInstance;
HHOOK hHook=0;
HWND SysTray=0;
HWND NotifyWnd=0;
DWORD dwExplorerThreadId=0,dwExplorerProcessId=0;

char msg[256];
HANDLE hCon=0;
HWND wCon=0;

BOOL WINAPI DllEntryPoint(HINSTANCE hInstDll,DWORD fdwReason,LPVOID)
{
   switch(fdwReason) {
   case DLL_PROCESS_ATTACH:
      hInstance=hInstDll;
      break;
   case DLL_THREAD_ATTACH:
      break;
   case DLL_PROCESS_DETACH:
      break;
   case DLL_THREAD_DETACH:
      break;
   }
   return TRUE;
}

void SetTrayHook()
{
   if(hHook==NULL) {
      SysTray=FindWindow("Shell_TrayWnd",NULL);
      NotifyWnd=FindWindowEx(SysTray,0,"TrayNotifyWnd",0);
      dwExplorerThreadId=GetWindowThreadProcessId(SysTray,
         &dwExplorerProcessId);
      hHook=SetWindowsHookEx(WH_CALLWNDPROC,HOOKPROC(MsgProc),
         hInstance,dwExplorerThreadId);
      //PostThreadMessage(dwExplorerThreadId,WM_NULL,0,0);
   }
   else {
      UnhookWindowsHookEx(hHook);
      hHook=NULL;
   }
   return;
}

bool isFirst=true;
LRESULT CALLBACK MsgProc(int nCode,WPARAM wParam,LPARAM lParam)
{
   if(isFirst) {
      isFirst=false;
      isNT=IsNT();
      SysTray=FindWindow("Shell_TrayWnd",NULL);
      NotifyWnd=FindWindowEx(SysTray,0,"TrayNotifyWnd",0);
      // To display messages
      AllocConsole();
   
0
 
NickRepinCommented:
Here is the full answer to your Q. It works for NT and 95 and more simple.


//***************************************************************
//  sh.cpp - Enumerate system tray icons - main module (console app).
//  Run it in window, not in the full-screen mode.
//
//  Creates the console, attached to the Explorer.
//  The icons info will be printed on this console.
//  Icons itself will be painted on the console window caption
//       at 200-pixels offset from the left.
//
//  Console automatically destroys after 10 sec.
//
//  Link with shdll.dll.
//
//***************************************************************
#define STRICT

#include <windows.h>
#include <iostream.h>
#include <conio.h>


void _import SetTrayHook();

void main(void)
{
   SetTrayHook();

   Sleep(15000);

   SetTrayHook();
}
//*******************************************
// File: shdll.cpp. Compile as DLL
//*******************************************
#define STRICT
#include <windows.h>
#include <commctrl.h>
#include <stdlib.h>

bool IsNT()
{
   OSVERSIONINFO v;
   v.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
   ::GetVersionEx(&v);
   return v.dwPlatformId==VER_PLATFORM_WIN32_NT;
}

bool isNT=IsNT();

void _export SetTrayHook();
void enumerateIcons();
void out(char* p=0);
LRESULT CALLBACK MsgProc(int,WPARAM,LPARAM);

HINSTANCE hInstance;
HHOOK hHook=0;
HWND SysTray=0;
HWND NotifyWnd=0;
DWORD dwExplorerThreadId=0,dwExplorerProcessId=0;

char msg[256];
HANDLE hCon=0;
HWND wCon=0;

BOOL WINAPI DllEntryPoint(HINSTANCE hInstDll,DWORD fdwReason,LPVOID)
{
   switch(fdwReason) {
   case DLL_PROCESS_ATTACH:
      hInstance=hInstDll;
      break;
   case DLL_THREAD_ATTACH:
      break;
   case DLL_PROCESS_DETACH:
      break;
   case DLL_THREAD_DETACH:
      break;
   }
   return TRUE;
}

void SetTrayHook()
{
   if(hHook==NULL) {
      SysTray=FindWindow("Shell_TrayWnd",NULL);
      NotifyWnd=FindWindowEx(SysTray,0,"TrayNotifyWnd",0);
      dwExplorerThreadId=GetWindowThreadProcessId(SysTray,
         &dwExplorerProcessId);
      hHook=SetWindowsHookEx(WH_CALLWNDPROC,HOOKPROC(MsgProc),
         hInstance,dwExplorerThreadId);
      //PostThreadMessage(dwExplorerThreadId,WM_NULL,0,0);
   }
   else {
      UnhookWindowsHookEx(hHook);
      hHook=NULL;
   }
   return;
}

bool isFirst=true;
LRESULT CALLBACK MsgProc(int nCode,WPARAM wParam,LPARAM lParam)
{
   if(isFirst) {
      isFirst=false;
      isNT=IsNT();
      SysTray=FindWindow("Shell_TrayWnd",NULL);
      NotifyWnd=FindWindowEx(SysTray,0,"TrayNotifyWnd",0);
      // To display messages
      AllocConsole();
      hCon=CreateFile("CONOUT$",GENERIC_READ|GENERIC_WRITE,
         FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,0);
      SetConsoleMode(hCon,ENABLE_PROCESSED_OUTPUT|ENABLE_WRAP_AT_EOL_OUTPUT);
      CONSOLE_SCREEN_BUFFER_INFO bi;
      GetConsoleScreenBufferInfo(hCon,&bi);
      bi.dwSize.Y=200;
      SetConsoleScreenBufferSize(hCon,bi.dwSize);
      SetConsoleTitle("Nick's console");
      wCon=FindWindow(0,"Nick's console");
      out("We are in the Explorer!\r\n");
      wsprintf(msg,"Console wnd=%X\r\n\r\n",wCon);
      out();

      enumerateIcons();

      Sleep(10000);  // Wait 10 sec

      CloseHandle(hCon);
      FreeConsole();
   }
   return CallNextHookEx(hHook,nCode,wParam,lParam);
}

struct TWIconDataT {
   DWORD imageIndex;  // image index, -1 if no image in iconList
   union {
      NOTIFYICONDATAW dw;
      NOTIFYICONDATAA da;
   };
};

typedef TWIconDataT* pTWIconDataT;

struct TWIconsInfoT {
   int Cnt;
   pTWIconDataT* iconData;
};

struct TWDataT {
   DWORD unknown[7];
   TWIconsInfoT* iconsInfo;
   HIMAGELIST    iconList;
};

typedef pTWIconDataT WINAPI (*COMCTL32_332_T) (TWIconsInfoT* info,int index);
COMCTL32_332_T COMCTL32_332;

void enumerateIcons()
{
   // Load useful function
   HINSTANCE hLib=LoadLibrary("COMCTL32.DLL");
   COMCTL32_332=(COMCTL32_332_T) GetProcAddress(hLib,LPCSTR(332));

   TWDataT* twd=(TWDataT*)GetWindowLong(NotifyWnd,0);

   wsprintf(msg,"Proc=%X, NotifyWnd=%X, data=%X\r\n",COMCTL32_332,
      NotifyWnd,twd);
   out();

   int cnt=twd->iconsInfo->Cnt;  // icons count

   if(cnt==0) {
      out("No tray icons!\r\n");
      return;
   }

   wsprintf(msg,"Icons count=%d",cnt);
   out();

   int x=200; // Offset for icon painting

   for(int i=cnt-1;i>=0;i--) {
      wsprintf(msg,"\r\n\r\n# %d *****************\r\n",i); out();
      pTWIconDataT p=COMCTL32_332(twd->iconsInfo,i);
      wsprintf(msg,"ImageIndex=%d\r\n",p->imageIndex); out();
      wsprintf(msg,"hWnd=%X\r\n",p->dw.hWnd); out();
      wsprintf(msg,"uID=%d\r\n",p->dw.uID); out();
      wsprintf(msg,"uFlags=%d\r\n",p->dw.uFlags); out();
      wsprintf(msg,"uCallbackMessage=%d\r\n",p->dw.uCallbackMessage); out();
      wsprintf(msg,"hIcon=%X\r\n",p->dw.hIcon); out();
      memset(msg,0,sizeof(msg));
      strcpy(msg,"szTip=");
      if(isNT)
         wcstombs(msg+strlen(msg),p->dw.szTip,sizeof(p->dw.szTip)/2);
      else
         strcpy(msg+strlen(msg),p->da.szTip);
      out();

      HICON icon=ImageList_GetIcon(twd->iconList,p->imageIndex,ILD_NORMAL);
      wsprintf(msg,"Real icon=%X\r\n",icon);

      // Draw icon
      HDC dc=GetWindowDC(wCon);
      ImageList_Draw(twd->iconList,p->imageIndex,dc,x,4,ILD_NORMAL);
      ReleaseDC(wCon,dc);
      x+=30;
   }
}

void out(char* p)
{
   DWORD dwWritten;
   if(p) strcpy(msg,p);
   WriteConsole(hCon,msg,strlen(msg),&dwWritten,0);
}

0
 
itzikfCommented:
#include "stdafx.h"
#include <tlhelp32.h>

BOOL CALLBACK enumThreadWndProc(HWND hWnd, LPARAM lParam);

void Delete_Outlook_Systray_Icon()
{

     HWND hWnd = FindWindowEx(NULL, NULL, "rctrl_renwnd32", NULL);
     if (hWnd==NULL)
     {
          AfxMessageBox("Outlook Window not found");
          return;
     }
     
     DWORD dwProcessID;
     DWORD dwThreadID = GetWindowThreadProcessId(hWnd, &dwProcessID);

     if (dwThreadID==0)
     {
          AfxMessageBox("Outlook Thread not found");
          return;
     }


    BOOL          bFound      = FALSE;
    HANDLE        hModuleSnap = NULL;
    MODULEENTRY32 me32        = {0};
 
    // Take a snapshot of all modules in the specified process.

    hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessID);
    if (hModuleSnap == (HANDLE)-1)
     {
          AfxMessageBox("Could not creat Tool-Help snapshot for the Outlook process");
          return;
     }


    // Fill the size of the structure before using it.

    me32.dwSize = sizeof(MODULEENTRY32);
 
    // Walk the module list of the process, and find the module of
    // interest.

    if (!Module32First(hModuleSnap, &me32))
     {
          AfxMessageBox("Could find any module for the Outlook process");
          return;
     }

     bFound = false;
    do
    {
          if (lstrcmpi(me32.szModule, "Outlook.exe") == 0)
          {
            bFound = true;
               break;
        }
    }
    while (!bFound && Module32Next(hModuleSnap, &me32));
 
 
    // Do not forget to clean up the snapshot object.

    CloseHandle (hModuleSnap);
 
     if (!bFound)
     {
          AfxMessageBox("Could not identify Outlook Module name");
          return;
     }

     bool bIconDeleted = false;
     BOOL bScanToLast =
          EnumThreadWindows(dwThreadID, enumThreadWndProc, (LPARAM)&bIconDeleted);
     if(!bIconDeleted)
     {
          AfxMessageBox("Could not find or delete Outlook Notification Icon");
          return;
     }
     
     if (bScanToLast)
     {
          AfxMessageBox("Fishy: Had to scan ALL Outlook windows but anyway seems to delete Outlook Notification icon");
          return;
     }
}

BOOL MyTaskBarDeleteIcon(HWND hwnd, UINT uID)
{
    BOOL res;
    NOTIFYICONDATA tnid;
 
    tnid.cbSize = sizeof(NOTIFYICONDATA);
    tnid.hWnd = hwnd;
    tnid.uID = uID;
         
    res = Shell_NotifyIcon(NIM_DELETE, &tnid);
    return res;
}

BOOL CALLBACK enumThreadWndProc(HWND hWnd, LPARAM lParam)
{
     if (!MyTaskBarDeleteIcon(hWnd, 0))
          return true;

     *(bool*)lParam = true;

     char msg[512];
     wsprintf(msg,"Icon Deleted. window = %x", hWnd);
     AfxMessageBox(msg, MB_OK);
     return false;
}
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

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.

  • 9
  • 5
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now