Форум: "WinAPI";
Текущий архив: 2006.07.02;
Скачать: [xml.tar.bz2];
ВнизSendMessage из разных процессов Найти похожие ветки
← →
MaxxSoft © (2006-03-28 09:00) [0]Есть приложение (П1), для которого реализован интерфейс обмена данными через сообщения Windows. В нем регистрируется ДЛЛ, и функция которой передается управление при выборе определенного пункта меню. Эта функция активирует другое приложение (П2) для ввода некоторых данных. После ввода данных П2 вызывает другую функцию из этой же ДЛЛ, для пересылки данных в П1.
При посылке сообщений из первой функции (вызываемой из П1) все работает прекрасно:
// WPWnd - дескриптор первого приложения (П1)
// TWPModDataCell - специальная структура для передачи данных запроса
Query := "SELECT PAR1, PAR2 FROM TABLE1 WHERE PAR3 = "PAR3_VALUE"";
QueryResult := PWPModDataCell(SendMessage(WPWnd, WM_SQLOPEN, Integer(PChar(Query)), 0));
if (Assigned(QueryResult)) then
begin
Par1 := StrToInt(CellByName(QueryResult, "PAR1")^.Value);
Par2 := StrToInt(CellByName(QueryResult, "PAR2")^.Value);
ShowMessage("DATA FROM DB:" + #13 +
"PAR1 = " + IntToStr(Par1) + #13 +
"PAR2 = " + IntToStr(Par2));
SendMessage(WPWnd, WM_SQLFREE, Integer(QueryResult), 0);
end;
Но при вызове этого же кода из П2, строка запроса передается неправильно - приходит всякий мусор. Как решить проблему?
← →
Сергей М. © (2006-03-28 09:08) [1]см. WM_COPYDATA
← →
MaxxSoft © (2006-03-28 09:40) [2]Дело в том, что П1 не написано не мной и исходников нет, в документации к нему описан интерфейс обмена данными именно таким образом...
← →
Сергей М. © (2006-03-28 09:49) [3]
> MaxxSoft © (28.03.06 09:40) [2]
Я не знаю, что и кем писано, но приведенный тобой код не может быть использован для интерпроцессной передачи данных произвольного размера.
Для этого как раз и существует специальное сообщение WM_COPYDATA.
← →
MaxxSoft © (2006-03-28 10:49) [4]Пойдем другим путем.
Один процесс создает поток, в котором создается виртуальное окно функцией AllocateHWND(), как отправить сообщение этому окну из другого процесса. Имеется ввиду, как получить дескриптор этого виртуального окна в другом процессе?
← →
Сергей М. © (2006-03-28 11:14) [5]
> как получить дескриптор этого виртуального окна в другом
> процессе?
Это не виртуальное, это самое "настоящее" полноценное окно.
Если взаимодействующие приложения твоей разработки, то нет повода что-то "искать" - приложения могут использовать условное бродкаст-сообщение для информирования друг-друга о хендлах своих окон.
← →
MaxxSoft © (2006-03-28 11:37) [6]В том то все и дело, что приложения уже готовые, задача стоит написать библиотеку для связи этих приложений.
← →
Сергей М. © (2006-03-28 11:46) [7]
> приложения уже готовые
А откуда эти "готовые приложения" узнают про твою библиотеку ?
← →
MaxxSoft © (2006-03-28 11:49) [8]У них есть интерфейс регистрации библиотеки и имени функции.
← →
Сергей М. © (2006-03-28 12:01) [9]Проще всего в таком случае отказаться от интерпроцессного инф.обмена посредством сообщений в пользу MMF (memory mapped files).
При загрузке твоей библ-ки в АП того или иного процесса в ходе инициализации она создает (или открывает, если уже создан) MMF c неким условным именем (см. Create/OpenFileMapping, MapViewOfFile). Данные в области этого MMF видны доступны (с указанными при создании/открытии правами) всем заинтересованным в обмене процессам.
← →
MaxxSoft © (2006-03-30 10:18) [10]Теперь другая проблема, как завершить поток из чужого процесса?
type
TMsgEvent = function (Msg: TMessage): Boolean of Object;
TWndThread = class (TThread)
private
FOnMessage: TMsgEvent;
procedure WndProc(var Message: TMessage);
public
Wnd: HWND;
ModMessages: TWPModMessages;
property OnMessage: TMsgEvent read FOnMessage write FOnMessage;
procedure Execute; override;
procedure Terminate; virtual;
destructor Destroy; override;
procedure FreeData;
end;
{$R *.res}
procedure TWndThread.WndProc;
begin
with Message do
begin
case Msg of
WM_USER + 1: FreeData;
WM_CLOSE: PostQuitMessage(0);
else DefWindowProc(Wnd, Msg, WParam, LParam);
end;
end;
end;
procedure TWndThread.FreeData;
begin
Destroy;
end;
procedure TWndThread.Terminate;
begin
PostThreadMessage(ThreadId, WM_QUIT, 0, 0);
inherited;
end;
destructor TWndThread.Destroy;
begin
Terminate;
inherited;
end;
procedure TWndThread.Execute;
var
Msg: TMsg;
begin
Wnd := AllocateHWND(WndProc);
while ((not Terminated) and (GetMessage(Msg, 0, 0, 0))) do DispatchMessage(Msg);
DeallocateHWND(Wnd);
end;
Пытаюсь завершить созданный поток из другого приложения, посылаю в окну в созданном потоке сообщение
SendMessage(PPWnd, WM_CLOSE, 0, 0);
или
SendMessage(PPWnd, WM_USER + 1, 0, 0);
Вылетает exeption...
← →
Сергей М. © (2006-03-30 10:28) [11]
> Вылетает exeption
Ставь брейкпойнт в теле WndProc(), пройди пошагово и увидишь где у тебя ошибка ..
← →
Leonid Troyanovsky © (2006-03-30 11:52) [12]
> MaxxSoft © (30.03.06 10:18) [10]
> SendMessage(PPWnd, WM_CLOSE, 0, 0);
Тут ничего преступного нет, выход из message loop произойдет
по WM_QUIT, все сообщения в очереди будут обработаны до того.
> SendMessage(PPWnd, WM_USER + 1, 0, 0);
А вот так делать нельзя, т.к. FreeData разрушит поток.
Такие вещи, как FreeData делают, например, в OnTerminate
(если нужно разрушать в первичном потоке) или
после DeallocateHwnd.
Вообще, закрыть такой поток можно просто:
PostThreadMessage(ThreadId, WM_QUIT, 0, 0).
И еще раз, not Terminated, в данном случае, не нужен.
--
Regards, LVT.
← →
MaxxSoft © (2006-03-30 12:09) [13]Разобрался, дело было в том, что запускал поток так:
WndTread := TWndThread.Create(false);
WndThread.Execute;
А конструктор с параметром false автоматически запускает Execute, таким образом Execute запускался 2 раза...
Появилась новая неприятность, даже не знаю с какой стороны подойти...
Итак в ДЛЛ 2 внешних функции, одна запускает поток, вторая его завершает.
Приложение, вызывающее функцию запуска загружает библиотеку динамически, и, после вызова функции, соответственно выгружает ее (библиотеку). В этот момент вылетает ошибка обращения к памяти, насколько я понимаю, из-за того, что обработчик потока (созданного окна) находится в ДЛЛ, а она выгружена.
Вероятно я считаю неправильно. Для проверки написал тестовое приложение, загружающее библиотеку статически - все работает, загружаю динамически - та же ошибка, из этого сделал вывод, что проблема в выгрузке ДЛЛ из памяти.
Возможно ли как-нибудь решить эту проблему?
← →
Сергей М. © (2006-03-30 13:01) [14]
> Возможно ли как-нибудь решить эту проблему?
Просто не создавай себе эту "проблему" - и решать ее не придется.
Подумай сам - код из загруженной библиотеки запущен на выполнение (тем или иным образом, неважно каким) и в этот момент ты даешь системе команду на выгрузку библ-ки, т.е. требуешь "выкинуть" этот код из АП процесса .. Нонсенс ? Конечно ! ... Выгрузка библ-ки должна происходить лишь тогда, когда ни код ни данные в ее составе более не нужны, но никак не ранее этого момента.
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2006.07.02;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.012 c