![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Передача данных из одного приложения в другое
Pasha L © (2005-08-05 19:22:00)Вопрос: можно ли из одного приложения в другое передать данные не создавая для этого временного файла? (D6 WinXP)
Alexander Panov (2005-08-07 18:23:00) [21]см. высказывания.
Маг Похмеляйнен (07.08.05 0:11) [13]
Надёжней через именованный file mapping object.
Leonid Troyanovsky © (07.08.05 10:14) [16]
WM_COPYDATA передается через MMF (неименованный), создаваемый системой.
Дополнительный бонус - синхронизация с принимающим потоком.
Маг Похмеляйнен (07.08.05 10:58) [17]
О, это общеизвестно.
Однако:
1) Нужно знать хэндл окна, которому посылаем данные. Неудобно. Некрасиво.
2) Данные структурированные, большого объёма. Каждый раз придётся паковать их в буферок, отдавать системе (PostMessage(WM_COPYDATA...)), система делает мап,.... ДОлго.
3) На вкус и цвет... :o)
1 решается простым Broadcast-сообщением.
2 а для именованный file mapping objectэто не нужно, как я понимаю?
3. Только не надо подменять объективные характеристики своими пристрастиями.
Alexander Panov (2005-08-07 18:17:00) [22]Маг Похмеляйнен (07.08.05 11:17) [19]
Вот ещё один недостаток WM_COPYDATA.
Можно привести первый недостаток?
забыл (2005-08-07 18:13:00) [23]сокеты не дело - ибо файрик ругнется (даже не смотря на 127.0.0.1, ибо порт открыли, данные передаются) - юзверя спугнете...
майлслоты мне показались не сильно приятными =)
пайпы - отличное решение, как и WM_COPYDATA. сам использую последнее чаще всего.
DDE - вполне разумно
y-soft (2005-08-07 11:50:00) [24]>palva © (06.08.05 22:57) [10]
С передачей строк при таком способе возникнут заморочки. Это же не WM_COPYDATA
Придется использовать что-то типа FileMapping, а тогда можно обойтись вообще без посылки сообщений, а использовать события Windows для уведомления (или вообще таймер) + мьютекс для синхронизации (при односторонней связи необязателен), тогда и наличие окна необязательно...
P.S. IMHO по простоте реализации и универсальности очень удобны каналы (Pipes) - не надо думать о синхронизации и сразу можно установить режим чтения/записи сообщений...
Маг Похмеляйнен (2005-08-07 11:17:00) [25]Да, действительно, через PostMessage это сделать заморочно.
Вот ещё один недостаток WM_COPYDATA.
:o)
Leonid Troyanovsky (2005-08-07 11:00:00) [26]
> Маг Похмеляйнен (07.08.05 10:58) [17]
> придётся паковать их в буферок, отдавать системе (PostMessage(WM_COPYDATA...)),
Только не Post.
--
Regards, LVT.
Маг Похмеляйнен (2005-08-07 10:58:00) [27]О, это общеизвестно.
Однако:
1) Нужно знать хэндл окна, которому посылаем данные. Неудобно. Некрасиво.
2) Данные структурированные, большого объёма. Каждый раз придётся паковать их в буферок, отдавать системе (PostMessage(WM_COPYDATA...)), система делает мап,.... ДОлго.
3) На вкус и цвет... :o)
Leonid Troyanovsky (2005-08-07 10:14:00) [28]
> Маг Похмеляйнен (07.08.05 00:11) [13]
> Надёжней через именованный file mapping object.
WM_COPYDATA передается через MMF (неименованный), создаваемый системой.
Дополнительный бонус - синхронизация с принимающим потоком.
--
Regards, LVT.
Leonid Troyanovsky (2005-08-07 09:54:00) [29]
> GuAV © (06.08.05 23:32) [12]
> > IMHO, Data must be PCOPYDATASTRUCT
> Там и так указатель на COPYDATASTRUCT.
Где там?
--
Regards, LVT.
GuAV (2005-08-07 00:49:00) [30]Маг Похмеляйнен (07.08.05 0:11) [13]
Чем это надёжнее WM_COPYDATA ?
Маг Похмеляйнен (2005-08-07 00:11:00) [31]Надёжней через именованный file mapping object.
GuAV (2005-08-06 23:32:00) [32]
> IMHO, Data must be PCOPYDATASTRUCT
Там и так указатель на COPYDATASTRUCT.
>а установление SetLength
>после присвоения особого смысла не имеет, т.к., если
> там уже есть #0, он все и ограничит.
Эт правда, тем более, что исходя изData.cbData := Length(AString);там этого #0 нету, поэтому возможно AV.
Прaвильно - черезSetString.
Leonid Troyanovsky (2005-08-06 23:11:00) [33]
> Джо © (06.08.05 02:38) [8]
> function DecodeData (Msg: TMessage): string;
> var
> Data: COPYDATASTRUCT;
> begin
> Data := PCopyDataStruct (Msg.LParam)^;
> Result := PChar(Data.lpData);
> SetLength(Result,Data.cbData);
IMHO, Data must be PCOPYDATASTRUCT, а установление SetLength
послеприсвоения особого смысла не имеет, т.к., если
там уже есть #0, он все и ограничит.
--
Regards, LVT.
palva (2005-08-06 22:57:00) [34]Можно так: Обе программы по функции RegisterWindowMessage получают идентификатор сообщения. Система гарантирует, что этот идентификатор будет уникальным (не будет мешать другим программам) и будет одним и тем же, если программы при обращении к функции зададут один и тот же строковый параметр. А потом одна программа посылает широковещательное PostMessage (с первым параметром HWND_BROADCAST) а вторая выбирает его из своей очереди по GetMessage/PeekMessage. Насколько я понимаю, вторая программа должна иметь главное окно.
y-soft (2005-08-06 09:15:00) [35]>Pasha L (06.08.05 01:42) [7]
Расскажите о каком-нибудь поподробнее
В принципе, наверное, проще всего сделать, как в [8]. Тонкости неплохо описаны у Рихтера. Только здесь есть один не совсем приятный нюанс - приложение должно знать хендл окна получателя. Да и синхронный характер SendMessage не всегда удобен
Так же довольно несложно использовать MailSlots или Pipes, немного сложнее - сокеты...
Можно использовать и упомянутый Вами способ с использованием промежуточного файла, но в его качестве лучше использовать объект FileMapping и, возможно, позаботится о синхронизации...
В общем-то никто не запрещает использовать и технологию COM, но в реализации это будет значительно сложнее, особенно, если свяжетесь с маршалингом. Да и скорость будет не слишком высокой...
Ну и напоследок можно упомянуть о такой экзотике, как DDE...
Примеров не привожу из-за объемности материала, но их множество в MSDN...
Джо (2005-08-06 02:38:00) [36]В случае нескольких строк, по-моему, нет нужды городить огород. Воспользуйся посылкой сообщения WM_COPYDATA.
Примерчик.
В первом приложении делаешь такую оболочку для посылки:
procedure SendString (AHandle: THandle; const AString: string);
var
Data: COPYDATASTRUCT;
begin
Data.dwData := 0;
Data.cbData := Length(AString);
Data.lpData := PChar(AString);
SendMessage(AHandle,WM_COPYDATA,0,Integer(@Data))
end;
Посылаешь строку вот так
SendString (H,'Hello!');
где H - хэндл нужного окна во втором приложении. Например, получаешь его при помощи FindWindow.
---
Во втором приложении в нужной форме объявляешь метод, получающий управление при приходе сообщения WM_COPYDATA:
TForm1 = class(TForm)
private
procedure WmCopyData (var Message: TMessage); message WM_COPYDATA;
...
implementation
...
procedure TForm1.WmCopyData(var Message: TMessage);
begin
ShowMessage (DecodeData(Message));
Message.Result := 1
end;
И пишешь функцию-оболочку для выдирания текста:
function DecodeData (Msg: TMessage): string;
var
Data: COPYDATASTRUCT;
begin
Data := PCopyDataStruct (Msg.LParam)^;
Result := PChar(Data.lpData);
SetLength(Result,Data.cbData);
end;
Здесь есть несколько нюансов, о которых ты можешь прочесть в MSDN или Справке из Platform SDK по сообщению WM_COPYDATA. Один из них в том, что первая программа не получит управления до тех пор, пока вторая не обработает сообщение, так как используется SendMessage, а не PostMessage. В общем, читай, разбирайся...
Pasha L (2005-08-06 01:42:00) [37]Я хочу передать несколько строк из одного приложения в другое. Я мог бы из одного приложения вывести эти строки в файл, а из другого - прочитать файл. А потом файл удалить. Но уверен, что есть более рациональный способ.
//Андрей Молчанов (05.08.05 20:07) [3]
Хотелось бы выполнить задачу стандартными "инструментами"
//y-soft © (05.08.05 22:26) [6]
Расскажите о каком-нибудь поподробнее.
y-soft (2005-08-05 22:26:00) [38]Способов много
3DxFantastika (2005-08-05 22:15:00) [39]Сокеты .. лучшее и универсальное решение!
Eraser (2005-08-05 21:51:00) [40]Pasha L (05.08.05 19:22)
Советую покопать в сторону MailSlots.