Есть вопрос по взаимодействию com-объекта и клиента
От: Relder Россия  
Дата: 02.08.06 11:35
Оценка:
Суть проблемы такая (возможно, ниже я немного буду путаться в терминах — не судите строго):

(1) Есть com-объект (точнее, приложение-сервер автоматизации, допустим он обзывается MyOwnOnject), который желательно иметь при работе в _единственном_ экземпляре и связанного с единственным клиентом (то есть, в памяти сидит _один_ клиент, который и получает с этого объекта данные).

Я так понимаю, что единственность указывается таким вызовом? (в секции initialization — пишу я это все на Delphi):


TAutoObjectFactory.Create(ComServer, MyOwnObject_Auto, Class_MyOwnObject_Auto,
                          ciSingleInstance, tmApartment);


Или для этого нужно что-то еще?

Пока что у меня получилась модель такая: к одному серверу могут прицепиться несколько клиентов (что не хотелось бы!), все они могут вызывать методы
сервера, но получает от сервера сообщения только один (первый присоединившийся) клиент. Как-то мне это не нравится.



(2) Как быть в том случае, если клиент аварийно прекратил работу (а сервер остался в памяти в блаженном неведении о смерти своего клиента)? При запуске
нового клиента, присоединить его к серверу не получается (точнее, клиент может вызывать методы сервера, но не получает от сервера сообщения, каковые, полагаю, адресуются "первому клиенту", уже помершему).

Как вариант (очень кривой, я в курсе), попробовал такую связку:


var
  ActiveObj: IUnknown;  TheWindow : HWND;
  ProcessID: Integer;   ProcessHandle : THandle;

 * * *

  GetActiveObject (CLASS_MyOwnObject_Auto, nil, ActiveObj);
  if ActiveObj <> nil then
  begin
    TheWindow := FindWindow('TFormMyOwnObject', nil);
    GetWindowThreadProcessID(TheWindow, @ProcessID);
    ProcessHandle := OpenProcess(PROCESS_TERMINATE, FALSE, ProcessId);
    TerminateProcess(ProcessHandle,4);
    CloseHandle(ProcessHandle);
    FServer := CoMyOwnObject_Auto.Create;
  end
  else
    FServer := CoMyOwnObject_Auto.Create;


или, допускаю более "цивилизованный" вариант, заменить секцию с вызовом TerminateProcess на

  PostMessage(FindWindow('TFormMyOwnObject', nil), WM_QUIT, 0, 0);


(и уже потом вызов CoMyOwnObject_Auto.Create),

добавив в сервер процедуру отлова сообщения WM_QUIT, в каковой процедуре можно сделать необходимые действия (сбросить файлы, погасить транзакции, etc.) и завершить работу сервера.

Hо!

(a) Как мне завершить работу сервера из него самого, когда у него уже есть "нить" (???) связывающая его с "первым" (умершим) клиентом? Простые методы типа Application.Terminate не действуют, так как как он начинает жаловаться, мол "There are still active COM objects in this application", выводить менюшки и прочее. Хотя, конечно, можно попробовать "самоубиваться" через TerminateProcess (а самого себя так можно убить?).

(b) И как мне вообще узнать (изнутри сервера) — задействован ли сервер в данный момент или свободен?

(с) И как можно (изнутри сервера, при условии положительных ответов на вопросы a и b) разорвать эту "нить"?



(3) К слову, в Win XP кусок кода с TerminateProcess у меня работал "на ура". А в Win98 — уже как-то не хочет. Я пока не разбирался углубленно (нету у меня под 98'ми установленного Delphi, пошагово не пройдешь), но нет ли тут уже каких-то известных подводных камней?




Заранее спасибо. Буду благодарен за любую помощь, включая и предметные ссылки на RTFM (я вообще, не вполне хорошо ориентируюсь в com-технологии), хотя,
конечно, более детальные ответы были бы для меня совсем щастьем!

Elder
Re: Есть вопрос по взаимодействию com-объекта и клиента
От: Alexey Frolov Беларусь  
Дата: 04.08.06 08:00
Оценка:
Здравствуйте, Relder, Вы писали:

R>Суть проблемы такая (возможно, ниже я немного буду путаться в терминах — не судите строго):

[skipped]

Ну с сервером понятно, реализуете Singleton и он будет в единственном экземпляре. А вот насчет единственного клиента, я как то не понял идею. Нужно чтобы в памяти был запущен только один клиент и попытки запустить еще пресекались? может расскажете для чего нужно такое поведение, вдруг подскажем другое решение? или может не другое
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.