![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Альтернатива SendMessage [D7, WinXP]
Игорь404 © (2009-04-07 09:40:00)Уважаемые, существует ли альтернатива использованию конструкции SendMessage() для передачи сообщения объекту тестируемого приложения.
Дело в том, что данная конструкция не работает на практике, применительно к объектам следующих классов: TreeView и DateTimePicker (В тестируемом приложении используются модификации этих классов. SysTreeView32, SysDateTimePick32). Всевозможные варианты использования SendMessage() уже перебрал и не добился результатов. Неделя потраченного времени и нервов. Возможно существует другой способ отправки сообщений?
Существует ли возможность изменения значения (к примеру даты в DateTimePicker) через адреса памяти текущего процесса?
Заранее благодарен.
(2009-07-13 13:10:00) [1]Удалено модератором
Игорь404 (2009-04-10 15:11:00) [2]Задача решена. Я внедрил DLL в процесс тестируемого приложения и передал ему
SendMessage(handle, DTM_SETSYSTEMTIME, GDT_VALID, Longint(@dateTime));
теперь все работает, не тестировал еще с TreView, но думаю и здесь проблем не будет.
Осталось решить проблему с адаптированием DLLки к разным элементам управления, но это уже другая история.
p.s. Ради таких минут мы и живем друзья, спасибо! :)
аноним (2009-04-10 13:36:00) [3]
> Хорошо, не будем - только и ты плз глупости не пиши о переписывании
> программы и читай внимательней, желательно с самого начала.
> Приложение чужое, поэтому у тебя и спрашивают, что именно
> в чужом приложении стоит переписать?
Где там сказано, что код чужой ? Там сказано, что процесс другой.
Игорь404 (2009-04-10 11:41:00) [4]Возможно я ввел кого-то в заблуждение, но к коду тестируемого приложения доступа нет.
Rouse_ (2009-04-10 09:11:00) [5]
> Такие откровенные глупости писать не надо. Хорошо ?
Хорошо, не будем - только и ты плз глупости не пиши о переписывании программы и читай внимательней, желательно с самого начала. Приложение чужое, поэтому у тебя и спрашивают, что именно в чужом приложении стоит переписать?
аноним (2009-04-10 04:15:00) [6]
> DateTimePicker переписать или TreeView ?
Такие откровенные глупости писать не надо. Хорошо ?
Я понимаю делфи и все такое, но есть же предел в конце концов.
Игорь Шевченко (2009-04-09 20:30:00) [7]
> Лучше переписать прогу чтобы она принимала WM_COPYDATA и
> не волноваться за будующее
DateTimePicker переписать или TreeView ?
аноним (2009-04-09 15:29:00) [8]
> Никак не могу понять, чем WM_COPYDATA (будучи упомянутой
> уже дважды в данной ветке) может помочь при отправке того-
> же DTM_SETSYSTEMTIME?
Привилегий хватит писать в память чужого процесса ? Как Виста на такое отреагирует и Вин7 (я точно не знаю)?
Лучше переписать прогу чтобы она принимала WM_COPYDATA и не волноваться за будующее
Игорь404 (2009-04-09 14:19:00) [9]Наверное много времени бы потратил на отладку :)
К счастью человек эволюционирует и на смену рогаткам, с чрезвычайно узким спектром применения, приходят мелкокалиберные винтовки, с ненамного большим, но однако же большим. И все это я к тому, что не факт что только по "воробьям", если ты меня понимаешь. :) В мое случае приложение должно быть достаточно гибким, чтобы в перспективе была возможноть оперативно изменять его согласно новым требованиям. Мне кажется в случае с DLL injection приложение будет обладать достаточной гибкостью и масштабируюмостью.
Rouse_ (2009-04-09 13:32:00) [10]Из пушки по воробьям :) Хотя... хозяин барин.
ЗЫ: Если что - то этот пример (по ссылке) нормально выгружается только из своего собственного процесса, более полный вариант этой демки можешь взять тут: http://forum.sources.ru/index.php?showtopic=248156&st=0entry2057057
Игорь404 (2009-04-09 13:26:00) [11]Дело в том, что элементов управления очень много и придется адаптировать код к каждому отдельно (или адаптировать ко всем сразу).
Но вот на что я наткнулся
"Внедрение библиотеки через CreateRemoteThread"
http://delphisite.ru/faq/vnedrenie-biblioteki-cherez-createremotethread
Выполнение собственного кода в чужом процессе.
Осталось только взвесить эти два варианта на предмет трудоемкости и выбрать наиболее гибкое и легкореализуемое...
Rouse_ (2009-04-09 10:10:00) [12]
> как в этом случае быть с TreeView?
Вот тебе старый пример работы с CommCtrl окнами в удаленном процессе, делай по аналогии:
////////////////////////////////////////////////////////////////////////////////
//
// ****************************************************************************
// * Unit Name : RemoteSysListView32
// * Purpose : Демо работы с удаленным SysListView32
// * Author : Александр (Rouse_) Багель
// * Copyright : © Fangorn Wizards Lab 1998 - 2007
// * Version : 1.01
// * Home Page : http://rouse.drkb.ru
// ****************************************************************************
//
program RemoteSysListView32;
{$APPTYPE CONSOLE}
uses
Windows,
SysUtils,
CommCtrl;
var
hwndRemoteSysListView: HWND = 0;
hProcess: THandle = 0;
dwProcessID: DWORD = 0;
dwBytesWriten: DWORD;
nItemCount: Integer = 0;
I, nTextLength: Integer;
cchTextMax: Integer = 255;
plviRemoteLVItem: PLVItem = nil;
lviRemoteLVItem: LV_ITEM;
pszText: PChar = nil;
svText: ShortString;
ARect: TRect;
pRemoteRect: Pointer = nil;
function GetFirstChild(hwndValue: HWND): HWND;
begin
Result := GetWindow(hwndValue, GW_CHILD);
end;
function Translate(Value: String): String;
begin
SetLength(Result, Length(Value));
AnsiToOem(@Value[1], @Result[1]);
end;
begin
// Ищем SysListView32 рабочего стола
hwndRemoteSysListView := GetFirstChild(GetFirstChild(FindWindow('ProgMan', nil)));
if hwndRemoteSysListView = 0 then ExitProcess(GetLastError);
// Получаем количество элементов (ярлыков на рабочем столе)
nItemCount := ListView_GetItemCount(hwndRemoteSysListView);
// Получаем ID процесса, которому принадлежит найденное окно
GetWindowThreadProcessId(hwndRemoteSysListView, @dwProcessID);
if dwProcessID = 0 then ExitProcess(GetLastError);
// Открываем процесс
hProcess := OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwProcessID);
if hProcess = 0 then ExitProcess(GetLastError);
// Выделяем в нем память под текстовый буффер
pszText := VirtualAllocEx(hProcess, nil, cchTextMax,
MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE);
if GetLastError <> 0 then ExitProcess(GetLastError);
// Выделяем в нем память под структуру LVITEM
plviRemoteLVItem := VirtualAllocEx(hProcess, nil, SizeOf(LV_ITEM),
MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE);
if GetLastError <> 0 then ExitProcess(GetLastError);
// Заполняем структуру
ZeroMemory(@lviRemoteLVItem, SizeOf(LV_ITEM));
lviRemoteLVItem.mask := LVIF_TEXT;
lviRemoteLVItem.pszText := pszText;
lviRemoteLVItem.cchTextMax := cchTextMax;
// Пишем ее в память удаленного процесса
if not WriteProcessMemory(hProcess, plviRemoteLVItem, @lviRemoteLVItem,
SizeOf(LV_ITEM), dwBytesWriten) then ExitProcess(GetLastError);
// Выделяем в нем память под структуру TRect
pRemoteRect := VirtualAllocEx(hProcess, nil, SizeOf(TRect),
MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE);
if GetLastError <> 0 then ExitProcess(GetLastError);
// Получаем текст со всех элементов
for I := 0 to nItemCount - 1 do
begin
// Отправляем сообщение с указателем на выделенный буффер под LVITEM
nTextLength := SendMessage(hwndRemoteSysListView, LVM_GETITEMTEXT,
I, Integer(plviRemoteLVItem));
// Читаем результат
ZeroMemory(@svText, cchTextMax);
ReadProcessMemory(hProcess, lviRemoteLVItem.pszText,
@svText[1], nTextLength, dwBytesWriten);
// Чтобы получить координаты каждого элемента нужно подготовить структуру
ZeroMemory(@ARect, SizeOf(TRect));
ARect.Left := LVIR_ICON;
if not WriteProcessMemory(hProcess, pRemoteRect, @ARect,
SizeOf(TRect), dwBytesWriten) then ExitProcess(GetLastError);
// Посылаем сообщение для получения координат каждого элемента
SendMessage(hwndRemoteSysListView, LVM_GETITEMRECT,
I, Integer(pRemoteRect));
// Читаем результат
ReadProcessMemory(hProcess, pRemoteRect,
@ARect, SizeOf(TRect), dwBytesWriten);
Writeln(Translate(PChar(@svText[1])));
Writeln(Translate(
Format('- координаты: Left = %d, Top = %d, Right = %d, Bottom = %d',
[ARect.Left, ARect.Top, ARect.Right, ARect.Bottom])));
end;
// Освобождаем ранее выделенную память
VirtualFreeEx(hProcess, pszText, 0, MEM_RELEASE);
VirtualFreeEx(hProcess, plviRemoteLVItem, 0, MEM_RELEASE);
// Закрываем описатель процесса
CloseHandle(hProcess);
Readln;
end.
clickmaker (2009-04-09 10:00:00) [13]> даже еслиб и получилось, то как в этом случае быть с TreeView?
а почему тривью должно вдруг обрабатывать wm_copydata?
Игорь404 (2009-04-09 07:24:00) [14]С WM_COPYDATA у меня таки ничего не получилось. Да даже еслиб и получилось, то как в этом случае быть с TreeView?
Игорь Шевченко (2009-04-08 22:51:00) [15]Rouse_ © (08.04.09 22:31) [22]
> Никак не могу понять, чем WM_COPYDATA (будучи упомянутой
> уже дважды в данной ветке) может помочь при отправке того-
> же DTM_SETSYSTEMTIME?
ну если DTM_SETSYSTEMTIME не получается, может DateTimePicker на WM_COPYDATA согласится...
Rouse_ (2009-04-08 22:31:00) [16]Никак не могу понять, чем WM_COPYDATA (будучи упомянутой уже дважды в данной ветке) может помочь при отправке того-же DTM_SETSYSTEMTIME?
аноним (2009-04-08 19:00:00) [17]
> Про маршаллинг сообщений.Некоторые структуры таки оказываются
> "чудом" в чужом процессе. Все структуры сообщений, что меньше
> WM_USER
Тут как раз таки никакого волшебства, система про эти сообщения знает, знает размер структуры или строки и копирует в адресное пространство все это.
В данном случае надо это делать самому, без магии все ручками
ИМХО тут WM_COPYDATA лучший вариант
Rouse_ (2009-04-08 15:57:00) [18]
> Так точно не получится, надо в другое приложение DLL внедрять
Библиотеку то зачем?
guav (2009-04-08 15:53:00) [19]аноним (08.04.09 08:23) [16]
> Что именно ?
Про маршаллинг сообщений.
Некоторые структуры таки оказываются "чудом" в чужом процессе. Все структуры сообщений, что меньше WM_USER.
Человек (08.04.09 08:56) [17]
> А должно быть влияние ?
Нет, но это ж неочевидно ;-)
аноним (2009-04-08 12:09:00) [20]
> И вам читать Рихтера :-)
Мало читать плохо, и много читать тоже вредно, начинает мерещиться всякое, всякое страшное и не возможное