| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C++ Builder > EnumChildWindow() - не находит HWND |
| Автор: fridkaratel 22.10.2007, 08:07 |
| Имеется программа стороннего разработчика (ПСР). ПСР использует для обработки данные из файла set.ini. Моя программа (МП) подставляет необходимые данные в этот файл. Чтобы пользователю было удобно и чтобы не светить ПСР, я решил ее запускать через SW_HIDE, и нажимать TToolButton "Start". После нажатия ПСР выполняет действия и выводит статус выполения (заверщения) задачи на TCGauge. Чтобы как-то отображать статус в МП, я думал получать через, скажем, каждые 2 сек сообщения от TCGauge о статусе выполнения. И сразу возникли две проблемы: 1. Не могу работать с TToolButton, так как не удается получить Handle. 2. Не могу работать с TCGauge, так как не удается получить Handle. Пробовал через разные сканеры, но результат тот же - этих контролов не видно. Также не видно и TLabel... но это ладно - мне она не нужна... Как нажать кнопку и получить статус выполнения? Доп. информация: ПСР не зажата упаковщиками, не зашифрована, можно спокойно декомпилировать и получить нахвания всех процедур, форм и т.п. вещей. Как быть? |
| Автор: fridkaratel 22.10.2007, 09:35 |
| и как же тогда реализовать мне то, что необходимо? :( |
| Автор: pandrew 22.10.2007, 10:07 |
| 1. Придумать другой алгоритм. 2. Обратиться к разработчику ПСР с просьбой добавить необходимую функциональность. 3. Отказаться от данной ПСР. 4. ... |
| Автор: fridkaratel 22.10.2007, 11:47 |
| я эту тему уже обсудал здесь... http://forum.codenet.ru/showthread.php?t=42524 но толку это не принесло... можно почитать и предложить свои версии о том, что дальше делать... |
| Автор: pandrew 22.10.2007, 12:43 |
| Вы пытаетесь управлять чужим софтом, который для этого не предназначен. Можно полностью имитировать действия юзера: позиционирование курсора, клики на кнопках и т.д. Для считывания показаний Gauge можно делать скриншоты и анализировать картинку, хоть через персептроны. Однако, самый дешевый способ - обратиться к разработчику ПСР с просьбой о доработке, например добавить реализацию интерфейса COM. Либо реализовать всю функциональность заново. |
| Автор: fridkaratel 22.10.2007, 13:20 |
| я думал про подключаемую dll... но толку то нет - как получить значение TCGauge? кнопка TToolButton - фиг с ней, а вот как получить статус? Была еще такая идея - на примере ArtMoney - искать данные в памяти процесса... скорей всего, данные о прогрессе имеют постоянный адрес, так как смысла делать его динамическим нет... Итак, какие варианты? |
| Автор: dumb 22.10.2007, 14:15 |
| учи олбанский - либо китайский, либо ассемблер... |
| Автор: fridkaratel 22.10.2007, 15:16 |
| короче, как я понял - самы надежный и лучший выход из ситуации - на асме встроить доп. функционал в программу... блин, капец... :( |
| Автор: 586 22.10.2007, 15:37 | ||||
ПСР написана на Delphi или Builder'e? Если на Builder'e, с помощью tdump посмотри таблицу экспорта exe-шника ПСР.
и в DLL можно сделать такой трюк:
|
| Автор: fridkaratel 22.10.2007, 16:18 |
| программа написана на Borland C++ Builder 6. 586, то, что ты предложил уже можно пробовать реализовывать? или еще подождать? |
| Автор: 586 22.10.2007, 16:23 | ||
Посмотри таблицу экспорта того приложения, или сюда выложи. Может там и нет ничего... |
| Автор: fridkaratel 22.10.2007, 17:43 |
| хех... интересная задачка а можно по пунктам, что мне необходимо сделать? ни разу с этим не сталкивался... PS: но tdump я нашел |
| Автор: 586 22.10.2007, 18:22 |
| 1. Выполнить -> cmd.exe 1.1 mode con lines=9999 // если не хватает места в консоли 2. tdump C:\programs\app.exe 3. В самом низу будут выписаны ресурсы, выше - таблица экспорта (см. код выше) это таблица секций, а не экспорта |
| Автор: dumb 22.10.2007, 18:33 | ||
или просто
|
| Автор: fridkaratel 22.10.2007, 18:46 | ||
| блин... я такую же таблицу видел в дебаггере, когда пытался найти таблицу экспорта... и еще - у меня ошибка выдавалась, мол не могу открыть файл... я думал-думал, а оказалось, что я просто директорию не поменял - по умолчанию при cmd стоит ведь "Мои документы", а программу я положил в C:\1... капец, короче... уже скарились мозги вконец... Так, вот выкладываю таблицу...
|
| Автор: dumb 22.10.2007, 19:32 |
| такое ощущение, что это программа, демонстрирующая возможности компонентов с закладки Samples... у этой проги полезная функциональность есть вообще? |
| Автор: fridkaratel 22.10.2007, 19:36 |
И дальше - больше, поэтому необходимо как-то научиться ей управлять, т.к. контролы меняться не так сильно будут, а вот функционал - сильно... если есть необходимость - могу дать ссылку для скачивания программы... |
| Автор: dumb 22.10.2007, 19:46 |
| необходимость может быть только у тебя. у нас же - только любопытство и желание/нежелание помочь. давно надо было. |
| Автор: 586 22.10.2007, 19:58 | ||||
DLL
программа-стартер
|
| Автор: fridkaratel 23.10.2007, 04:18 |
| я могу дать и исходники тоже... ;) просто смысла не вижу особого - там все, практически, по-другому, версия ведь аж 2.0... блин... не могу теперь ссылку на программу найти Добавлено через 10 минут и 53 секунды вот ссылка для скачивания с другого форума: http://unlock.in.ua/forum/showpost.php?p=5&postcount=1 вот еще есть, правда версию не знаю: http://siriust.ru/index_p.php?fid=2916 вот вроде как самая последняя версия... ;) Лучше ее скачать, а потом уже остальные, если желание будет http://profimobile.ru/list-files/view.php?fid=3594&dir_id=82 А предложенный код уже можно пробовать? или это для ознакомления, чтобы с чего-то начать? |
| Автор: 586 23.10.2007, 07:53 |
да |
| Автор: fridkaratel 23.10.2007, 13:10 |
| есть проблема... создаю New Application -> Other -> DLL Wizard, вставляю код в юнит, компилирую, потом создаю стартер и его запускаю... при нажатии на кнопку запускается программа, но стартер выдает ошибку: "Инициализация DLL в удалённом процессе завершена с ошибкой". 1. Правильно ли я создаю DLL? просто у тебя BOOL WINAPI DllMain, а у меня int WINAPI DllMain 2. Что делать? |
| Автор: dumb 23.10.2007, 14:08 |
| судя по тому, что ты не смог разобраться с этим примером(а надо было лишь соблюсти правильность имен .exe/.dll), то тебе остается только просить кого-то сделать готовый механизм, так как этот пример нужно еще обработать напильником - добавить, как минимум, возможность взаимодействия(ipc) между dll и запускающей программой. |
| Автор: fridkaratel 23.10.2007, 14:22 |
| в том то и дело, что я изменил имена всех программ и подключаемого DLL Стартер - starter.exe Модуль DLL - control.dll Программа, которой необходимо управлять - ft.exe Все это я поместил в папку C:\1, соответственно, измнил все пути на этот, чтобы не делать ExtractFilePath и т.п. вещей, и чтобы не запутаться в путях... Но в итоге запускается по нажатию кнопки только программа, а модуль не подключается... я даже просмотрел список DLL, использующихся программой ft.exe Выдается сообщение, которое я написал выше... Так как быть ? PS: а ничего страшного, если я вместо int WINAPI MAIN поставил твое значение - BOOL WINAPI MAIN? |
| Автор: 586 23.10.2007, 15:50 | ||||
норм. Это одно и тоже.
Тут идёт проверка, что вернула фунуция LoadLibraryA. Причина ошибки скорее из-за: 1. указан не правильный путь 2. DllMain вернула 0. |
| Автор: fridkaratel 23.10.2007, 16:51 |
| проблема была в строке: String DllPath=ExtractFilePath(ExcludeTrailingBackslash(ExtractFilePath(Application->ExeName))); я сомневался и хотел почистить ее на c:\1, но решил, что тут идет какое-то специальное вычисление пути... оказалось, что просто удаляет последний путь, то есть вместо c:\1\2 напишет c:\1.. Все ок - работает ;) Спасибо... Только почему при наведении курсора на кнопку закрытия окна появляются сообщения "ОК"? И как отслеживать изменение TCGauge? PS: как я рад |
| Автор: fridkaratel 24.10.2007, 05:17 |
| так, теперь необходимо не установить какие-либо параметры контролов, а получить при обновлении... какие здесь будут варианты? создать TTimer, который будет через определенное время посылать команды МП или создать TApplicationEvent, который будет перехватывать все сообщения? может есть еще что сделать можно? PS: чувствую, что конец уже не за горами - и тема будет разобрана полностью |
| Автор: 586 24.10.2007, 21:20 | ||
| А в чём конкретно проблемы? В динамическом создании TApplicationEvents? TTimer? Я не знаю, как отследить изменение TCGauge. В exe-шнике экспортируется ф-ция __fastcall SetProgress(long). Можно попробовать её перехватить.
Какие сообщения? CGauge же графический компонент, а не оконный. Если только другого характера сообщения перехватывать, напр. нажатие кнопки, изменение заголовка окна и т.п. PS Выложи скрин окна программы, которую ты перехватываешь. |
| Автор: fridkaratel 25.10.2007, 04:28 |
| Вот... как происходит все: 1. Занести данные в файл, из которого ПСР автоматически подставляет данные в нужные поля 2. Нажать на кнопку Download 3. Получать значение TCGauge снизу ВОт скрин... |
| Автор: fridkaratel 28.10.2007, 16:40 |
| возник один вопрос... пытаюсь создать динамически: TToolButton *tb_my = NULL; а потом найти компонент на форме и присвоить... но компилятор ругается, мол expression syntax error... что делать? |
| Автор: 586 29.10.2007, 05:19 | ||||
без кода трудно что-либо сказать...
|
| Автор: fridkaratel 29.10.2007, 08:59 |
| ок, спасибо... у меня глюк был - было два файла Unit1.cpp и откуда-то взятый Unit1.h, который вообще не нужне в DLL а как можно организовать обмен сообщениями между двумя программами? мне необходимо посылать команды другому приложению, но в DLL надо как-то объявить... Интересует такой вот формат: Программа1 -> SendMessage(<param>) -> Программа2 switch (<param>) { case <something>: ....} Как лучше всего это сделать? То есть я бы хотел посылать какие-нибудь переменные из Программы1 в Программу2, в свою очередь Программа2 обработала операции, связанные с посланной переменной и отправила Программе1. Получается логикак как у клиент-серверного приложения... |
| Автор: pandrew 29.10.2007, 10:37 | ||
Существует много способов организации связи между двумя приложениями. Поиск рулит. Вариант с SendMessage тоже возможен. Надо только помнить об асинхронности обмена. |
| Автор: fridkaratel 29.10.2007, 11:05 |
| искал и читал - наткнулся на pipe... это капец - сложно слишком... |
| Автор: pandrew 29.10.2007, 11:36 |
| В BCB есть пример обмена через COM. тут еще: http://forum.vingrad.ru/forum/topic-141384/unread-1/hl/%25D0%25BE%25D0%25B1%25D0%25BC%25D0%25B5%25D0%25BD/index.html http://www.citforum.ru/programming/32less/les21.shtml Для обмена через посылку сообщений, все что надо, как-то узнать кому посылать сообщения (например через FindWindow). Любая программа имеет право послать любому окну SendMessage(Handle,msg,wParam,lParam), msg >= WM_USER, wParam и lParam - твои параметры. В оконной процедуре принимающей стороны, надо их как-то обработать. Добавлено через 3 минуты и 4 секунды тут еще http://www.sql.ru/forum/actualthread.aspx?bid=21&tid=414150&hl=%ee%e1%ec%e5%ed Однако совсем просто не будет. |
| Автор: fridkaratel 29.10.2007, 16:30 |
| вот, я хочу через SendMessage() посылать свои сообщения через wParam и lParam, только как их принимать не знаю... PS: почитаю предложенное ;) |
| Автор: 586 29.10.2007, 16:59 | ||
из DLL в своё приложение? Поищи по форуму BEGIN_MESSAGE_MAP. |
| Автор: pandrew 29.10.2007, 17:21 | ||||
У каждого WinControl (и у TCustomForm) есть метод DefaultHandler(void *Message). Его можно подменить в производном классе (твоя форма) приблизительно так:
|
| Автор: fridkaratel 29.10.2007, 17:25 |
| 586, скачал исходники по одной из ссылок, которые предложил pandrew. pandrew, ок, поробую твой код применить |
| Автор: fridkaratel 29.10.2007, 17:50 | ||
| 586, а как вставить то, что ты предложил? и куда? как я понял, надо воткнуть вот это:
Но не понимаю - у меня же не инициализируется в DLL класс формы, а предложенный MESSAGE инициализируется в разделе public формы... что делать? Создать новую форму? есть другие варианты? ********************** pandrew, а как это встроить в DLL? ведь я не могу просто так взять и обхявить функцию void __fastcall TMyForm::DefaultHandler(void* Message)... у меня в DLL нет формы... как быть? |
| Автор: 586 29.10.2007, 18:36 |
| В DLL создавай поток и делай в нём на WinApi окно и цикл обработки сообщений. |
| Автор: fridkaratel 30.10.2007, 05:18 |
| а можно примерчик? |
| Автор: pandrew 30.10.2007, 10:53 | ||||
А при чем тут DLL? Ранее ты спрашивал:
В DLL есть экспортируемые функции. Кто мешает их просто вызвать? |
| Автор: fridkaratel 30.10.2007, 14:01 |
| да, есть два приложения, и между ними надо посылать и принимать сообщения... может я забыл упомянуть, но мне необходимо инициализировать функции посылки и приема сообщения в Программе 2 через DLL, т.е. в программе нет функций и объявлений - они должны быть в DLL... К Программе 1 есть доступ, и можно с ней делать все, что угодно, т.е. Программа 1 - это моя программа, а Программа 2 - не моя... вот... как тут быть? |
| Автор: 586 30.10.2007, 16:13 | ||
Поток нужен для того, чтобы функция DllMain завершилась (вернула 1 или 0 - модуль корректно загружен или нет). Система может ожидать завершения этой ф-ции и процесс может зависнуть. Поэтому делаем отдельный поток. Имя класса и заголовок окна задаёшь сам. В своём приложении ищешь с помощью ф-ции FindWindow. |
| Автор: fridkaratel 30.10.2007, 16:48 |
| 586, спасибо - буду пытаться ;) PS: а ты когда в аське бываешь? никак застать не могу.... по ней можно к тебе обращаться за помощью в срочных делах? |