Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: ActiveX/СОМ/CORBA > Корректное создание COM-сервера, как реализовать?


Автор: Caduser 24.1.2007, 06:18
Есть много информации о том как сделать свой COM-сервер (внешне-процессный EXE) с помощью мастера Delphi "Automation Object Wizard". Однако поведение такого сервера будет несколько иным, чем у скажем у Word, Exel и т.д.)
1. Если при подсоединении клиентского приложения, COM-сервер не был запущен то он автоматически запускается - это правильно. Однако если закрыть клиента, то закрывается и запущенный им сервер - ЭТО НЕ ПРАВИЛЬНО (например Word, после отсоединения клиента остается запущенным). Может я просто выбрал не ту модель - ciMultiInstance, tmApartment?
2. Для соединения с Word можно использовать примерно такой код:
Код

  try  // Пытаемся подключиться к запущенному Word
    AppWord := GetActiveOleObject('Word.Application');
  except // не смогли подключиться - запускаем новый экземпляр приложения  
     AppWord := CreateOleObject('Word.Application);
  end;

Однако для самодельного COM-сервера это не сработает, почему??? нужно делать так:
Код

  CreateComObject(CLASS_MyApp) as IMyApp;

Как заставить свой COM-сервер вести себя аналогично Word???

Автор: CatATonik 24.1.2007, 10:25
См. функции RegisterActiveObject и RevokeActiveObject

Автор: Caduser 24.1.2007, 14:22
Цитата(CatATonik @ 24.1.2007,  10:25)
См. функции RegisterActiveObject и RevokeActiveObject

Использование этих функций не помогло, приложение ведёт себя как и прежде: закрываем клиента - закрывается сервер. Вообще эти функции использует пример из JCL "jcl\examples\windows\delphitools\peviewer", не ясно зачем они? Может они срабатывают в Win98?

Автор: CatATonik 24.1.2007, 14:34
У меня срабататывают, может чего-то не так делаешь? Они предназначены ровно для того, что ты описал и работать должны под всеми виндами (может кроме Vista и виндовс 3.1  smile )

Автор: Caduser 25.1.2007, 05:01
Разобрался (спасибо CatATonik!), теперь работает как надо. В RegisterActiveObject необходимо устанавливать флаг ACTIVEOBJECT_STRONG тогда в процессе регистрации у объекта увеличивается счетчик ссылок и даже после отключения от объекта всех программ-клиентов объект из памяти не выгружается.
Вот работающий код:
Код

var
  FROTHandle: Integer;
  // ...
procedure TProgControl.Initialize;
begin
  inherited;
  OleCheck(RegisterActiveObject(Self as IUnknown, Class_PeViewerControl,
    ACTIVEOBJECT_STRONG, // вместо "ACTIVEOBJECT_WEAK"
    FROTHandle));
  {$IFDEF COMPILER5_UP}
  ComServer.UIInteractive := False;
  {$ENDIF}
end;

destructor TProgControl.Destroy;
begin
  OleCheck(RevokeActiveObject(FROTHandle, nil));
  inherited;
end;

initialization
  TAutoObjectFactory.Create(ComServer, TProgControl, Class_ProgControl,
    ciMultiInstance, tmApartment);

end.

Нашел еще одно решение:
Код

initialization
  TAutoObjectFactory.Create(ComServer, TProgControl, Class_ProgControl,
    ciMultiInstance, tmApartment);
  if Comserver.StartMode = smAutomation then
    ComObj.CoAddRefServerProcess;
finalization
  if Comserver.StartMode = smAutomation then
    ComObj.CoReleaseServerProcess;

так же увеличивает счетчик ссылок на единицу, однако для второго варианта уже не будет работать схема подключения типа:
Код

 try
    App1 := GetActiveOleObject('...');
  except
    try
      App1 := CreateOleObject('...');
    except
      ShowMessage('Не удалось подключиться!');
    end;
  end;

интересно почему?

Автор: CatATonik 25.1.2007, 09:35
Потому что RegisterActiveObject заносит объект в системный список активных OLE объектов, по которой и происходит поиск при GetActiveOleObject, видимо во втором варианте этого не происходит.

Автор: Caduser 26.1.2007, 01:42
Теперь все предельно ясно. Спасибо за помощь!

Автор: jashilko 6.5.2009, 13:54
У меня такая проблема, каждый клиент создаёт свой сервер что ли. То есть, я регистрирую в сервере событие, каждому клиенту по кнопке делаю реакцию на это событие и пишу обработчик, получается так, что в одном клиенте я событие вызвал, а в других оно не вызывается, почеум так может быть?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)