Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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
2-1149975785
learner
2006-06-11 01:43
2006.07.02
Правильное закрытие Handl - а


15-1149510150
oldman
2006-06-05 16:22
2006.07.02
Валуев защитил титул чемпиона мира.


2-1150369563
ttt_111
2006-06-15 15:06
2006.07.02
Как запретить запускать повторно уже запущенную программу?


3-1146131337
yaral
2006-04-27 13:48
2006.07.02
Как закрыть DataModule


15-1149584884
Kerk
2006-06-06 13:08
2006.07.02
Бойцовский клуб





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский