Получение списка иконок в трее
Иногда приложению требуется получить список иконок, находящихся в трее, а также список приложений, которые их туда разместили. Это может быть нужно для обнаружения некоторых скрывающихся приложений, для эмуляции кликов на иконках, ну или просто для спортивного интереса. В любом случае для получения списка иконок надо сделать следующее: найти в трее панель с иконками, при помощи сообщения TB_BUTTONCOUNT получить количество иконок, а затем через отправку сообщения TB_GETBUTTON получить всю необходимую информацию по каждой иконке. Теперь рассмотрим все шаги подробнее.Работать с вложенными окнами трея мы уже умеем, здесь практически то же самое, разница только в названиях классов дочерних окон.
Code (Assembler) : Убрать нумерацию
- ; Сегмент данных
- section '.data' data readable writeable
- ...
- class1 db 'Shell_TrayWnd',0 ; Название класса окна трея
- class2 db 'TrayNotifyWnd',0 ; Название класса панели уведомлений
- class3 db 'SysPager',0 ; Трей
- class4 db 'ToolbarWindow32',0 ; Панель с иконками
- ToolbarHandle dd ? ; Хэндл окна с иконками
- ...
- ; Сегмент кода
- section '.code' code readable executable
- ...
- ; Найти окно трея
- invoke FindWindow,class1,NULL
- or eax,eax
- jz exit_process
- ; Найти панель уведомлений
- invoke FindWindowEx,eax,NULL,class2,NULL
- or eax,eax
- jz exit_process
- ; Найти трей
- invoke FindWindowEx,eax,NULL,class3,NULL
- or eax,eax
- jz exit_process
- ; Найти панель иконок в трее
- invoke FindWindowEx,eax,NULL,class4,NULL
- or eax,eax
- jz exit_process
- ; Сохранить хэндл окна с иконками
- mov [ToolbarHandle],eax
- ...
Code (Assembler) : Убрать нумерацию
- ; Получить количество иконок в трее
- invoke SendMessage,eax,TB_BUTTONCOUNT,0,0
- or eax,eax
- jz exit_process
- ; Сохранить количество иконок в трее
- mov [IconsCount],eax
Ненадолго отвлечемся от трея и выделим блок памяти нужного размера в контексте процесса-владельца трея. Размер блока равен размеру структуры TBBUTTON.
Code (Assembler) : Убрать нумерацию
- ; Получить ID процесса-владельца трея
- invoke GetWindowThreadProcessId,[ToolbarHandle],ProcId
- ; Открыть процесс с полным доступом
- invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,[ProcId]
- or eax,eax
- ; Фокус не удался
- jz exit_process
- ; Сохранить хэндл процесса-владельца трея
- mov [hProcess],eax
- ; Выделить блок памяти в контексте процесса
- invoke VirtualAllocEx,[hProcess],NULL,dword sizeof.TBBUTTON,\
- MEM_COMMIT,PAGE_READWRITE
- or eax,eax
- jz exit_process
- ; Сохранить указатель на блок памяти
- mov [lpData],eax
Code (Assembler) : Убрать нумерацию
- ; Структура пользовательских данных иконки
- struct EXTRADATA
- Wnd dd ? ; Хэндл родительского окна иконки
- uID dd ? ; Стиль отображения иконки
- ends
Code (Assembler) : Убрать нумерацию
- ; Перебрать все иконки в трее
- loc_loop:
- dec [IconsCount]
- ; Получить иконку из трея с индексом IconsCount
- invoke SendMessage,[ToolbarHandle],TB_GETBUTTON,[IconsCount],[lpData]
- ; Прочитать структуру иконки
- invoke ReadProcessMemory,[hProcess],[lpData],button,\
- dword sizeof.TBBUTTON,BytesRead
- or eax,eax
- jz exit_process
- ; Прочиталась вся структура?
- cmp [BytesRead],sizeof.TBBUTTON
- jnz exit_process
- ; Прочитать пользовательские данные иконки
- invoke ReadProcessMemory,[hProcess],[button.dwData],extra,\
- dword sizeof.EXTRADATA,BytesRead
- or eax,eax
- jz exit_process
- ; Прочиталась вся структура?
- cmp [BytesRead],sizeof.EXTRADATA
- jnz exit_process
- ; Это скрытая иконка?
- mov eax,[extra.uID]
- and eax,80000000h
- or eax,eax
- ; Да, пропустить
- jnz loc_loop
- ; Окно процесса существует?
- invoke IsWindow,[extra.Wnd]
- or eax,eax
- jz loc_loop
- ; Получить Id процесса, чья иконка находится в трее
- invoke GetWindowThreadProcessId,[extra.Wnd],ProcTrayId
- ; Снимок процессов системы
- invoke CreateToolhelp32Snapshot,TH32CS_SNAPPROCESS,0
- mov ebx,eax
- ; Перебрать в цикле все процессы
- mov eax,sizeof.PROCESSENTRY32
- mov [ProcEntry.dwSize],eax
- invoke Process32First,ebx,ProcEntry
- @@:
- cmp eax,FALSE
- je @f
- ; Это нужный нам процесс?
- mov eax,[ProcEntry.th32ProcessID]
- cmp eax,[ProcTrayId]
- je @f
- ; Следующий процесс
- invoke Process32Next,ebx,ProcEntry
- or eax,eax
- jz loc_loop
- jmp @b
- @@:
- push eax
- ; Закрыть хэндл
- invoke CloseHandle,ebx
- pop eax
- ; Имя файла определить не удалось
- or eax,eax
- jz @f
- invoke wsprintf,buff,mask,ProcEntry.szExeFile
- add esp,12
- ; Записать имя файла в консоль
- invoke lstrlen,buff
- invoke WriteConsole,[stdout],buff,eax,BytesRead,NULL
- @@:
- ; Все иконки обработали?
- cmp [IconsCount],0
- ja loc_loop
- ; Очистить память и ресурсы
- invoke VirtualFreeEx,[ProcId],[lpData],0,MEM_RELEASE
- invoke CloseHandle,[ProcId]
В приложении консольная программа с исходником, выводящая на экран список исполняемых файлов всех приложений, иконки которых видны в трее.
Просмотров: 9043 | Комментариев: 9
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
brute
(14.12.2015 в 11:23):
Спасибо! буду дальше медитировать. Запускать код x32 на x64 - это извращение: зачем? - проще перекомпилировать без изменения исходников. В п.1 я пытался сказать, что сами структуры (по крайней мере, поле для иконки) для "ReadProcessMemory" для x32 на x64 не совпадают! Они различны, а в чём различие - не известно, так как не нашёл полного описания полей этих структур..
ManHunter
(14.12.2015 в 10:57):
1. Затем, что не получив одной структуры, нельзя узнать адрес другой. По чтению из памяти - NtWow64ReadVirtualMemory64, иначе ничего 32-битному процессу из 64-байтного адресного пространства не прочитать. Адаптация кода под x64 меня не интересует, я ей заниматься не собираюсь.
2. "Нет тела - нет дела". Читать тут тоже нечего.
3. Разве у треда есть иконки? Иконки есть у окна и у исполняемого файла. Если интересует какое окно принадлежит треду, то перебираешь все окна, проверяешь их процесс-владельца, затем проверяешь принадлежность треду, при совпадении выдергиваешь иконку из окна. Не забывай про IsWindowVisible.
2. "Нет тела - нет дела". Читать тут тоже нечего.
3. Разве у треда есть иконки? Иконки есть у окна и у исполняемого файла. Если интересует какое окно принадлежит треду, то перебираешь все окна, проверяешь их процесс-владельца, затем проверяешь принадлежность треду, при совпадении выдергиваешь иконку из окна. Не забывай про IsWindowVisible.
brute
(14.12.2015 в 09:59):
пытался сие повторить на PB.. Вот что получилось:
https://yadi.sk/d/Qt3ziCQMmCppF
Вопросы:
1. Зачем читаем из процесса в две разных структуры а не в одну? и где почитать про чтение инфы из процесса, в частности про строение структур/процессов в памяти для x32 и x64?
На Win7_64 не работает (в моем варианте)структура button_td.TRAYDATA - в твоем extra. Методом тыка (добавлением новых членов в структуру) удалось что-то получить, но всё равно не все иконки видны.
2. где почитать теорию про "скрытаю иконку"
3. Почему "ExtractIcon" криво/не похоже извлекает иконки?
пробовал также безрезультатно
SendMessage_(hwnd,#WM_GETICON,#ICON_SMALL,0)
GetClassLong_(hwnd,#GCL_HICONSM)
Вернее, понятно, что ExtractIcon извлекает иконки приложения, а не трэда/процесса этого приложения. Как извлечь иконку трэда?
https://yadi.sk/d/Qt3ziCQMmCppF
Вопросы:
1. Зачем читаем из процесса в две разных структуры а не в одну? и где почитать про чтение инфы из процесса, в частности про строение структур/процессов в памяти для x32 и x64?
На Win7_64 не работает (в моем варианте)структура button_td.TRAYDATA - в твоем extra. Методом тыка (добавлением новых членов в структуру) удалось что-то получить, но всё равно не все иконки видны.
2. где почитать теорию про "скрытаю иконку"
3. Почему "ExtractIcon" криво/не похоже извлекает иконки?
пробовал также безрезультатно
SendMessage_(hwnd,#WM_GETICON,#ICON_SMALL,0)
GetClassLong_(hwnd,#GCL_HICONSM)
Вернее, понятно, что ExtractIcon извлекает иконки приложения, а не трэда/процесса этого приложения. Как извлечь иконку трэда?
ManHunter
(01.09.2015 в 13:00):
Ясно дело ничего не выведет, или ты думал, что 32-битная программа вот так просто получит доступ к памяти 64-битного эксплорера?
Сергей
(01.09.2015 в 12:51):
Программа не работает. Ничего не вывело
ManHunter
(25.10.2010 в 08:36):
Здесь где-то сказано, что я пишу на дельфи?
URTUR
(25.10.2010 в 07:35):
ПОМОГИТЕ!!
Я пишу оболочку (или как это называется:) в Delphi (6,7)
и вот столкнулся с проблемой трея:
как получить список иконок на свою форму и работать с ними?!
(т.е эмулировать работу трея)..
К сожалению Google не помог! :(
Поэтому попал к Вам, т.к здесь имеется хоть какая-то информация:)
Буду очень признателен, если кто поделится куском кода или хотябы подскажет в какую сторону копать.. Заранее спасибо!.
Контактная информация: [мыло: del], [icq: del]
Я пишу оболочку (или как это называется:) в Delphi (6,7)
и вот столкнулся с проблемой трея:
как получить список иконок на свою форму и работать с ними?!
(т.е эмулировать работу трея)..
К сожалению Google не помог! :(
Поэтому попал к Вам, т.к здесь имеется хоть какая-то информация:)
Буду очень признателен, если кто поделится куском кода или хотябы подскажет в какую сторону копать.. Заранее спасибо!.
Контактная информация: [мыло: del], [icq: del]
ManHunter
(28.07.2010 в 10:15):
Дублируй, я не против.
umka
(28.07.2010 в 10:00):
А можно на Delphi продублировать???
В принципе, понятно, но есть пару мест...
Спасибо.
В принципе, понятно, но есть пару мест...
Спасибо.
Добавить комментарий
Заполните форму для добавления комментария