Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > Delphi: WinAPI и системное программирование > Найти окно по классу |
Автор: Danger 23.7.2009, 13:12 |
Привет всем, Вобщем, есть терминальный сервер, удаленные пользователи через терминал запускают определенную программу (уникальный класс окна, создаваемый программой, знаю). Нужно "пробежаться" по всем сессиям, и проверить наличие в них окна с определенным классом. Вот здесь уже обсуждалось: http://www.delphimaster.ru/cgi-bin/forum.pl?id=1239955786&n=5 попробовал, как описано - нифига не работает. Непонятно, как получить Desktop терминальной сессии ( WTSEnumerateSessions() перечисляет лишь имена сессий, но не windows stations). Максимум, могу получить список процессов терминальной сессии - но по ним же я не могу получить список окон, созданных этими процессами? Кто знает, посоветуйте, пожалста.. |
Автор: kami 23.7.2009, 17:59 |
http://msdn.microsoft.com/en-us/library/aa383833(VS.85).aspx возвращает массив http://msdn.microsoft.com/en-us/library/aa383864(VS.85).aspx, один из параметров которой - pWinStationName. Пройдя по массиву, найдя нужную терминальную сессию и WinSta, проходим по http://msdn.microsoft.com/en-us/library/ms682614(VS.85).aspx, находим нужный и http://msdn.microsoft.com/en-us/library/ms682615(VS.85).aspx. Добавлено через 8 минут и 36 секунд мда... поторопился немного. Для того, чтобы перечислить десктопы нужно открыть winSta, а в http://msdn.microsoft.com/en-us/library/ms684339(VS.85).aspx не учитывается сессия... |
Автор: Danger 24.7.2009, 05:21 | ||||
Кстати, в процессе я так и не понял, что там с windows station в терминальных сессиях. То ли, используется текущая (консольная) window station ('WInSta0'), либо для всех терминальных сессий window station называется всегда одинаково (упомянутый 'WinSta0'). Вообще, существует ли способ перечислить не сессии, а window station терминальных сессий? Насчет
Неясно, как связать данные, получаемые через WTSEnumerateProcesses() и CreateToolhelp32Snapshot(). Точнее, непонятно зачем нужна CreateToolhelp32Snapshot(), если WTSEnumerateProcesses() и так вернет список терминальных процессов? Может, CreateToolhelp32Snapshot() не нужен, или я что-то не понимаю? |
Автор: kami 24.7.2009, 12:33 | ||||||
afaik, каждой терминальной сессии соответствует одна (СВОЯ) winSta. А вот название ее может отличаться:
Наоборот ![]()
ну да, но окна-то вроде можно перечислить только для потока, а не для процесса (EnumThreadWindows), соответственно - просто список процессов ничего не даст... |
Автор: Danger 24.7.2009, 12:39 |
так что же делать? ![]() |
Автор: kami 24.7.2009, 12:52 |
попробуй так: CreateToolhelp32Snapshot>Thread32First|Next>EnumThreadWindows>GetClassName. Если нужно потом найти, в какой сессии это окно находится, то: в Thread32First|Next>THREADENTRY32 есть параметр th32OwnerProcessID. ProcessIDToSessionID, а зная SessionID можно получать о ней информацию из WTSQuerySessionInformation... |
Автор: Danger 24.7.2009, 20:16 | ||||
Такое ощущение, что в слепок попадают только потоки, принадлежащие текущей window station. Ни одного потока с процессов другого терминального пользователя..
GetProcessParams() - простейшая функция-"обёртка", возвращает некоторые параметры процесса.. |
Автор: kami 25.7.2009, 22:32 |
Так погляжу, на "соседнем" форуме посоветовали то, о чем я думал, но не хотел говорить - может есть менее обходной путь, чем запуск дополнительного процесса в каждой терминальной сессии... Но мнение Eraser -а в таких вопросах можно считать непререкаемым. Посему - уточняющие вопросы: версия ОС, в которой нужно найти нужное окно в терминальной сессии? |
Автор: Danger 26.7.2009, 00:21 | ||||
А что, если отталкиваться от списка процессов, возвращаемых WTSEnumerateProcesses() ? Т.е. получить список процессов, потом для каждого из них потоки, и в них искать окно? (без создания снимков).
MS Windows 2003 VLK Russian (R2), 32bit. |
Автор: kami 26.7.2009, 03:34 | ||
Не нашел функцию перечисления потоков по известному процессу. :( Покажете, как? Ага, значит предложенное Eraser-ом более чем возможно. |
Автор: Danger 26.7.2009, 10:58 | ||||||
|
Автор: kami 26.7.2009, 13:01 | ||||
|
Автор: Danger 26.7.2009, 15:06 |
Что характерно: запускаю Process Explorer от Sysinternals (в терминальной сессии), и он мне исправно перечисляет процессы других терминальных пользователей и потоки в них. Да банально: диспетчер задач отображает все процессы, всех пользователей (с указанием имени пользователя и параметров процесса). Как-то же он это делает? |
Автор: kami 26.7.2009, 20:45 | ||||||
afaik, он использует свой драйвер, устанавливаемый на время его работы (драйвер находится в его ресурсах). Иначе многие из его возможностей (к примеру - закрытие любого хендла) из user-mode выглядят нереально.
Да перечислить процессы и получить их параметры не так и сложно. А вот перечислить потоки процесса и окна потоков - с учетом
не вижу решения, кроме предложенного eraser-ом. P.S. А почему именно окно? Нельзя будет обойтись запущен/не запущен процесс? |
Автор: Danger 27.7.2009, 06:34 | ||||||||||
Возможно. Кстати, я вышел даже на NtQuerySystemInformation() с недокументированным параметром для перечисления потоков, но результат ее использования аналогичен функциям из ToolHelp - в список исправно попадают все процессы/потоки, но только текущей сессии. Ни один процесс, принадлежащий другому пользователю, просто не попадает в список.
Довольно проблематично проверять "аутентичность процесса". По каким критериям лучше всего определять соответствие процесса нужному? На первый взгляд, все параметры, по которым можно проверить, что запущен именно нужный исполнимый файл (работает нужный процесс) - ИМХО легко подделать обычному пользователю. Например, подменить exe-файл. |
Автор: kami 27.7.2009, 17:39 | ||
Хм... Обычный юзверь не должен иметь прав подменять рабочие экзешники (это если админ грамотный). Тем более он не должен иметь прав админа, чтобы дать себе такие права ![]() Но и без этого проверить оригинальность файла можно: действительное полное имя файла, всякие crc32, MD5 и иже с ними, доп. информация о версии файла... |