Savoir à quel programme appartient une icone de la zone de notification ("tray") et lister les icones

Soyez le premier à donner votre avis sur cette source.

Vue 9 100 fois - Téléchargée 573 fois

Description

Ce code permet de lister les icones du "Tray" à côté de l'horloge et de savoir à quel programme une icone appartient...

C'est une interprétation des données systèmes de cette zone (une barre d'outils sous ME/2000/XP)

Ce code a été testé sur 98/2000/XP

Source / Exemple :


//pour 95/98
#include "common.h"
//ToolHelp32
#include "tlhelp32.h"

//renvoie les icones du tray sous 9x
LPSYSTRAY GetTrayIcons_9x()
{
	//demande le hwnd du tray
	HWND hTray = GethWndTray();
	//alloue de la mémoire pour les infos sur le tray
	LPSYSTRAY lpSystray=(LPSYSTRAY)VirtualAlloc(NULL,sizeof(SYSTRAY),MEM_COMMIT,PAGE_READWRITE);
	if (lpSystray)
	{
		//demande le pointeur vers les infos du tray
		LPVOID lpData = (LPVOID)GetWindowLong(hTray,0);
		if (lpData)
		{
			DWORD pid=0;
			//demande le pid de Explorer.exe
			GetWindowThreadProcessId(hTray,&pid);
			//demande un handle de Explorer.exe pour lire dans son espace mémoire
			HANDLE hP = OpenProcess(PROCESS_VM_READ | PROCESS_VM_OPERATION,FALSE,pid);
			if (hP)
			{
				//lit les infos sur le tray
				if (ReadProcessMemory(hP,lpData,(LPVOID)lpSystray,sizeof(SYSTRAY),NULL))
				{
					//copie le pointeur vers l'entête de la liste d'icones
					lpData = (LPVOID)lpSystray->lpsysListHeader;
					//alloue de la mémoire pour l'entête de la liste d'icones
					lpSystray->lpsysListHeader = (LPNOTIFYLISTHEADER)VirtualAlloc(NULL,sizeof(NOTIFYLISTHEADER),MEM_COMMIT,PAGE_READWRITE);
					if (lpSystray->lpsysListHeader)
					{
						//lit l'entête de la liste d'icones
						if (ReadProcessMemory(hP,lpData,(LPVOID)lpSystray->lpsysListHeader,sizeof(NOTIFYLISTHEADER),NULL))
						{
							//nombre d'icones dans le tray
							ULONG dwCount =lpSystray->lpsysListHeader->dwCount;
							//copie le pointeur vers la liste de pointeurs vers les infos sur les icones
							lpData = (LPVOID)lpSystray->lpsysListHeader->lpNotifyDataList;
							//alloue de la mémoire pour cette liste de pointeurs
							lpSystray->lpsysListHeader->lpNotifyDataList = (LPNOTIFYENTRY*)VirtualAlloc(NULL,dwCount * sizeof(LPVOID),MEM_COMMIT,PAGE_READWRITE);

							//lit la liste de pointeurs
							if (ReadProcessMemory(hP,lpData,(LPVOID)lpSystray->lpsysListHeader->lpNotifyDataList,dwCount * sizeof(LPVOID),NULL))
							{
								//pour chaque pointeur
								for (UINT x =0; x < dwCount;x++)
								{
									//peut-être NT4 ?
									if (IsWindowsNT())
									{
										//on copie le notifyicondata
										if (((lpSystray->lpsysListHeader->lpNotifyDataList))[x] = (LPNOTIFYENTRY)VirtualAlloc(NULL,sizeof(NOTIFYICONDATAW)+4,MEM_COMMIT,PAGE_READWRITE))
											ReadProcessMemory(hP,(LPVOID)(((LPNOTIFYENTRY*)lpData)[x]),(LPVOID)((lpSystray->lpsysListHeader->lpNotifyDataList))[x],sizeof(NOTIFYICONDATAW)+4,NULL);
									}
									else
									{
										//on copie le notifyicondata
										if (((lpSystray->lpsysListHeader->lpNotifyDataList))[x] = (LPNOTIFYENTRY)VirtualAlloc(NULL,sizeof(NOTIFYICONDATAA)+4,MEM_COMMIT,PAGE_READWRITE))
											ReadProcessMemory(hP,(LPVOID)(((LPNOTIFYENTRY*)lpData)[x]),(LPVOID)((lpSystray->lpsysListHeader->lpNotifyDataList))[x],sizeof(NOTIFYICONDATAA)+4,NULL);
									}
								}
							}
						}
					}
				}
				//ferme le handle de Explorer.exe
				CloseHandle(hP);
			}
		}
	}
	//renvoie les infos
	return lpSystray;
}

//libère la mémoire allouée par GetTrayIcons_9x
void FreeTrayIcons_9x(LPSYSTRAY lpSystray)
{
if (lpSystray)
{
	if (lpSystray->lpsysListHeader)
	{
		ULONG dwCount =lpSystray->lpsysListHeader->dwCount;
		for (UINT x =0; x < dwCount;x++)
		{
			//libère chaque NOTIFYENTRY
			VirtualFree((LPVOID)(lpSystray->lpsysListHeader->lpNotifyDataList)[x],NULL,MEM_RELEASE);
		}

		//libère la liste
		VirtualFree((LPVOID)lpSystray->lpsysListHeader->lpNotifyDataList,NULL,MEM_RELEASE);
		//libère l'entête
		VirtualFree((LPVOID)lpSystray->lpsysListHeader,NULL,MEM_RELEASE);
	}
	//libère les infos du tray
	VirtualFree((LPVOID)lpSystray,NULL,MEM_RELEASE);
}
}

//renvoie le chemin et nom de l'exe d'un processus par son pid (sous 9x)
BOOL GetProcessNameFromPID_9x(DWORD pid,char* lpName)
{
	//si pas de tampon fournit
	if (lpName==NULL)
		return FALSE;

	//on crée une liste de processus
	HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,NULL);
	
	//on initialise la structure pour les infos sur un processus
	PROCESSENTRY32 Process={0};
	Process.dwSize = sizeof(PROCESSENTRY32);

	//demande la premier processus
	BOOL ret = Process32First(hSnap,&Process);

	//tant qu'il y a encore des processus à énumérer et que l'on a pas trouvé le processus que l'on veut
	while ((ret) && (Process.th32ProcessID != pid))
	{
		//demande le suivant
		Process.dwSize = sizeof(PROCESSENTRY32);
		ret = Process32Next(hSnap,&Process);
	}

	//libère la liste des processus
	CloseHandle(hSnap);

	//si on a trouvé
	if (ret)
	{
		//on copie le nom de l'exe
		strcpy(lpName,Process.szExeFile);
		return TRUE;
	}
	else
		return FALSE;
};

//renvoie les icones du tray sous windows ME
LPTRAY_ME GetTrayIcons_ME(int* nIcons)
{
HANDLE hProc=NULL;		//handle de Explorer.exe
HWND hTray=NULL;		//hWnd du tray
DWORD pid=0;			//identifiant d'un processus
HGLOBAL ptrVM=NULL;		//pointeur vers la zone mémoire pour TBBUTTON
DWORD ret=0;			//valeur de retour
LPVOID ptrTip=NULL;		//pointeur vers une chaîne Unicode (Tip ou Path)
TBBUTTON tbut;			//les infos sur le bouton
CHAR Char=0;		//contient un caractère unicode
int X,Y;				//compteurs
LPTRAY_ME pTray=NULL;		//pointeur vers l'entrée active du buffer Tray

//on initialise tbut
ZeroMemory((LPVOID)&tbut,sizeof(TBBUTTON));

//on demande le hWnd du tray
if ((hTray = GethWndTray())==NULL)
	return NULL;

//on demande l//identifiant de Explorer.exe
GetWindowThreadProcessId(hTray, &pid);

//on demande un handle de Explorer.exe
if ((hProc = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, pid))==NULL)
{
	//on alloue de la mémoire pour TBBUTTON
	if (ptrVM = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,sizeof(tbut)))
	{
		//on demande le nombre de boutons dans le tray

  • nIcons = (int)SendMessage(hTray, TB_BUTTONCOUNT, (WPARAM)NULL, (LPARAM)NULL);
//on alloue la mémoire nécessaire pour les infos pTray = (LPTRAY_ME)VirtualAlloc(NULL,(*nIcons) * sizeof(TRAY),MEM_COMMIT,PAGE_READWRITE); //pour chaque icone for (X = 0;X < *nIcons;X++) { //on demande les infos sur le bouton SendMessage(hTray, TB_GETBUTTON, X, (LPARAM)ptrVM); //on lit les infos sur le bouton ReadProcessMemory(hProc, ptrVM, (LPVOID)&tbut, sizeof(TBBUTTON), &ret); //on extrait les données utiles pTray[X].dwData = (LPVOID)tbut.dwData; pTray[X].fsState = tbut.fsState; pTray[X].fsStyle = tbut.fsStyle; pTray[X].iBitmap = tbut.iBitmap; pTray[X].idCommand = tbut.idCommand; pTray[X].iString = (LPVOID)tbut.iString; //la Tip ptrTip = (LPVOID)tbut.iString; Y=0; do { Char=NULL; //on lit chaque caractère unicode ReadProcessMemory(hProc, ptrTip, (LPVOID)&Char, sizeof(CHAR), &ret); pTray[X].sTip[Y] = Char; ptrTip = (LPBYTE)ptrTip + 1; Y++; //jusqu'au NULL } while (Char); //on lit les données sur l//icone (Path...) ReadProcessMemory(hProc, (LPVOID)tbut.dwData, (LPVOID)&(pTray[X]), 36, &ret); GetWindowThreadProcessId(pTray[X].hwnd,&pid); GetProcessNameFromPID_9x(pid,pTray[X].Path); } GlobalFree(ptrVM); } CloseHandle(hProc); } return pTray; } //pour NT #include "common.h" #include "psapi.h" //pointeurs de fonctions de PSAPI.dll (uniquement pour NT/2000/XP) //si l'on link avec, l'application ne marchera pas sous 9x //pour énumérer les modules de d'un processus typedef BOOL (_stdcall *lpEnumProcessModules)(HANDLE hProcess,HMODULE* lphModule,DWORD cb,LPDWORD lpcbNeeded); //pour obtenir le nom d'un module typedef DWORD (_stdcall *lpGetModuleFileNameExW)(HANDLE hProcess,HMODULE hModule,LPWSTR lpFilename,DWORD nSize); //renvoie la liste des icones présentes dans le tray //comme les infos se trouvent dans Explorer.exe et non dans notre processus //on doit allouée de la mémoire dans Explorer.exe pour pouvoir fournir un pointeur valide vers un TBBUTTON à SendMessage //cette fonction ne fonctionne que sous NT/2000/XP (car VirtualAllocEx n//est pas présent sous 9x) LPTRAY GetTrayIcons_NT(int* nIcons) { HANDLE hProc=NULL; //handle de Explorer.exe HWND hTray=NULL; //hWnd du tray DWORD pid=0; //identifiant d'un processus LPVOID ptrVM=NULL; //pointeur vers la zone mémoire pour TBBUTTON DWORD ret=0; //valeur de retour LPVOID ptrTip=NULL; //pointeur vers une chaîne Unicode (Tip ou Path) TBBUTTON tbut; //les infos sur le bouton TCHAR TChar=0; //contient un caractère unicode int X,Y; //compteurs LPTRAY pTray=NULL; //pointeur vers l'entrée active du buffer Tray //on initialise tbut ZeroMemory((LPVOID)&tbut,sizeof(TBBUTTON)); //on demande le hWnd du tray if ((hTray = GethWndTray())==NULL) return NULL; //on demande l//identifiant de Explorer.exe GetWindowThreadProcessId(hTray, &pid); //on demande un handle de Explorer.exe if ((hProc = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, pid))==NULL) return NULL; //on alloue de la mémoire pour TBBUTTON if ((ptrVM = VirtualAllocEx(hProc, NULL, sizeof(tbut), MEM_COMMIT, PAGE_READWRITE))==NULL) { CloseHandle(hProc); return NULL; } //on demande le nombre de boutons dans le tray
  • nIcons = (int)SendMessage(hTray, TB_BUTTONCOUNT, (WPARAM)NULL, (LPARAM)NULL);
//on alloue la mémoire nécessaire pour les infos pTray = (LPTRAY)VirtualAlloc(NULL,(*nIcons) * sizeof(TRAY),MEM_COMMIT,PAGE_READWRITE); //pour chaque icone for (X = 0;X < *nIcons;X++) { //on demande les infos sur le bouton SendMessage(hTray, TB_GETBUTTON, X, (LPARAM)ptrVM); //on lit les infos sur le bouton ReadProcessMemory(hProc, ptrVM, (LPVOID)&tbut, sizeof(TBBUTTON), &ret); //on extrait les données utiles pTray[X].dwData = (LPVOID)tbut.dwData; pTray[X].fsState = tbut.fsState; pTray[X].fsStyle = tbut.fsStyle; pTray[X].iBitmap = tbut.iBitmap; pTray[X].idCommand = tbut.idCommand; pTray[X].iString = (LPVOID)tbut.iString; //la Tip ptrTip = (LPVOID)tbut.iString; Y=0; do { TChar=NULL; //on lit chaque caractère unicode ReadProcessMemory(hProc, ptrTip, (LPVOID)&TChar, sizeof(TCHAR), &ret); pTray[X].sTip[Y] = TChar; ptrTip = (LPBYTE)ptrTip + 2; Y++; //jusqu'au NULL } while (TChar); //on lit les données sur l//icone (Path...) ReadProcessMemory(hProc, (LPVOID)tbut.dwData, (LPVOID)&(pTray[X]), 36, &ret); //demande la PID du processus propriétaire de l'icone GetWindowThreadProcessId(pTray[X].hwnd,&pid); //demand el nom de ce processus GetProcessNameFromPID_NT(pid,pTray[X].uniPath,255); } //on libère la mémoire allouée VirtualFreeEx(hProc,ptrVM,NULL, MEM_RELEASE); //on ferme le handle de Explorer.exe CloseHandle(hProc); //on renvoie le tout return pTray; } //renvoie le nom du processus par son PID BOOL GetProcessNameFromPID_NT(DWORD pid,WCHAR* lpName,DWORD cbName) { //si mauvais tampon if (lpName==NULL) return FALSE; //on charge PSAPI HMODULE hPSAPI = LoadLibrary("psapi.dll"); if (hPSAPI) { //on "active" les pointeurs vers EnumProcessModules et GetModuleFileNameEx lpEnumProcessModules EnumProcessModules = (lpEnumProcessModules)GetProcAddress(hPSAPI,"EnumProcessModules"); lpGetModuleFileNameExW GetModuleFileNameExW = (lpGetModuleFileNameExW)GetProcAddress(hPSAPI,"GetModuleFileNameExW"); if (EnumProcessModules && GetModuleFileNameExW) { //demande un handle du processus HANDLE hP = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,FALSE,pid); if (hP) { HMODULE hMod=NULL; //HMODULE de l'exe (toujours le premier module du processus) DWORD ret=0; //demande le HMODULE de l'exe (*EnumProcessModules)(hP,&hMod,sizeof(HMODULE),&ret); if (hMod) //demande le nom de l'exe (*GetModuleFileNameExW)(hP,hMod,(WCHAR*)lpName,cbName); //ferme le handle CloseHandle(hP); //libère PSAPI FreeLibrary(hPSAPI); return TRUE; } return FALSE; } } } //renvoie une chaine descriptive de l'état d'un bouton char* GetState_NT(BYTE fsState,char* Buff) { if (!Buff) return NULL; if ((fsState & TBSTATE_CHECKED) == TBSTATE_CHECKED) strcat(Buff,"Checked - "); if ((fsState & TBSTATE_ELLIPSES) == TBSTATE_ELLIPSES) strcat(Buff,"Ellipses - "); if ((fsState & TBSTATE_ENABLED) == TBSTATE_ENABLED) strcat(Buff,"Enabled - "); if ((fsState & TBSTATE_HIDDEN) == TBSTATE_HIDDEN) strcat(Buff,"Hidden - "); if ((fsState & TBSTATE_INDETERMINATE) == TBSTATE_INDETERMINATE) strcat(Buff,"Grayed - "); if ((fsState & TBSTATE_MARKED) == TBSTATE_MARKED) strcat(Buff,"Marked - "); if ((fsState & TBSTATE_PRESSED) == TBSTATE_PRESSED) strcat(Buff,"Pressed - "); if ((fsState & TBSTATE_WRAP) == TBSTATE_WRAP) strcat(Buff,"Wrap - "); return Buff; }

Conclusion :


Ce code fonctionne même lorsque l'option "Masquer les icones inactives" est activée (XP)...

Codes Sources

A voir également

Ajouter un commentaire Commentaires
Messages postés
1
Date d'inscription
dimanche 28 septembre 2003
Statut
Membre
Dernière intervention
2 mars 2010

Salut, et beau boulot. Je suis en train de réaliser une fonction un peu similaire a la tienne pour l'intégrer dans un programme, mais mon résultat est que TBBUTTON me retourne rien (toute les variables sont a zéro), je pensais que sa venais de mon programme mais en fait avec ta source donne le même résultat. Y a t-il quelque chose qui a changé au niveau du SendMessage 'TB_GETBUTTON' sur windows 7 ?
Messages postés
190
Date d'inscription
dimanche 17 avril 2005
Statut
Membre
Dernière intervention
18 mars 2009

excellent
Messages postés
539
Date d'inscription
vendredi 6 juin 2003
Statut
Membre
Dernière intervention
14 juillet 2010
1
ok j'ai compris merci pour ton explication

regarde une des sources ke j'ai creer ki utilise comme base ta source (j'espere ke tu m'en voudra po...)
http://www.cppfrance.com/code.aspx?ID=27923

di moi ce ke tu en penses....

j'ai rencontrais kelkes problemes
car parfois il y a po d'icone genre msn messenger, ou nvidia parameter,etc...
je sais po pourkoi ca contient po d'ico donc j'ai remplacer par l'ico du prog...
Messages postés
2676
Date d'inscription
vendredi 28 juin 2002
Statut
Membre
Dernière intervention
13 janvier 2016
20
salut

on en peut pas accéder à un imagelist d'un autre processus : un imagelist, c'est une zone mémoire pas un thread de fenêtre, donc tu ne peux pas lui envoyer de message...obtenir le handle de l'imagelist ne sert pas vraiment...

pour le hIcon : c'est le handle de l'icone et pas de l'imagelist : ce HICON (et pas HIMAGELIST) est un handle d'icone valide dans tous les processus du système (puis que pointant vers une zone > 0x80000000). Quand je récupère les infos sur un bouton dans un TBBUTTON avec TB_GETBUTTON le membre dwData est un pointeur vers la structure citée précédement (dans le processus Explorer.exe): et le membre hIcon est donc à 20 octets du début de la zone pointée par dwData. Il faut donc utiliser ReadProcessMemory pour lire la zone pointée par dwData dans Explorer.exe... Après tu peut utiliser ce HICON avec DrawIcon...

Je ne sais plus dans quel ordre j'ai fait la source C et la source VB mais de toute façon c'est la même méthode...

Bonne Prog

ShareVB
Messages postés
539
Date d'inscription
vendredi 6 juin 2003
Statut
Membre
Dernière intervention
14 juillet 2010
1
ok je te trouve pas tres clairs a ce nivo, cad ke ton hicon se rempli abec dwData kan tu li avec ton ReadProcessMemory bon pourkoi po ... j'arrive po a capter kan meme mais bon...

il y aurait po moyen de faire ca

himl2=(HIMAGELIST)SendMessage(GethWndTray(),TB_GETIMAGELIST,0,0); pour recup l'image list des boutton... c ce ke je suis entrain de faire..... di moi ce ke tu en penses..

sinon j'ai oublier de te feliciter, et d'une je te trouve clair dans ta facon de coder (tu mets po mal d'explication c ki est rare), , et ke d'autre part tu t gavé sur ce petit prog.... bien ke j'ai l'impression k'il soit adapter d'un VB ....

ciao
Afficher les 12 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.