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


Автор: Гость_Сергей 4.11.2004, 15:48
Здравствуйте. Я вынужден просить помощь, т.к. сам уже запарился искать решение.

Я пытаюсь написать ЛОКАЛЬНЫЙ COM-сервер. Описываю класс объекта на базе TComObject, без библиотеки типов и, соответственно, без флажка OleAutomation. Я надеюсь, что сделать это можно. Все интерфейсы объекта - наследники IUnknown (Custom Iterfaces). В конце модуля, как полагается стоит:

initialization
TComObjectFactory.Create(ComServer, TUrbOPC, Class_UrbOPC,
'OPCTest', Class_UrbOPC_Descr, ciMultiInstance, tmApartment);
end.

Проблема возникает, когда пытаюсь в клиенте получить фабрику класса. CoGetClassObject возвращает ошибку CO_E_SERVER_EXEC_FAILURE ($80080005).

Прокси для всех интерфейсов объекта зарегистрированы - проверял OleView.exe. На компьютере установлены другие локальные сервера с такой же функциональностью, т.е. имеют те же интерфейсы и подобные объекты, и при этом прекрасно запускаются и работают.

Думал, что надо создавать библиотеку типов, хотя клиент имеет описания всех интерфейсов. Потом обнаружил, что некоторые сервера и без библиотеки типов (тоже смотрел в OleView) работают.

Файл сервера регистрируется в реестре и находится правильно. Если в секции инициализации написать:

initialization
TComObjectFactory.Create(ComServer, TUrbOPC, Class_UrbOPC,
'OPCTest', Class_UrbOPC_Descr, ciMultiInstance, tmApartment);
ShowMessage('Object Factory Registered');
end.

, то при вызове в клиенте CoGetClassObject появится сначала сообщение, а потом выше описанная ошибка.

В чем же может быть проблема? Мучаюсь уже недели две, наверно.
Заранее спасибо

Автор: Гость_Сергей 5.11.2004, 15:37
Ну неужели никто не знает? Хотя бы где копать?

Кно нибудь еще встречался с этим?

Может быть единственное решение - использовать библиотеку типов?

Автор: Fantasist 5.11.2004, 21:26
Ошибка весьма неконткретная, означает что SCM не смог получить объект сервера. Причины могут быть разные. Вывод мессаджа еще ничего не означает. Например, в секции инициализации более поздно инициализируемого модуля может выскакивать исключение, которое приводит к краху запуска. Опять же могу посоветовать в ручную проверить соотвествие GUID-ов IDL с реестром. Это может быть и какая-нибудь глупая ошибка, типа перемещение более новой версии проекта в другое место, а в реестре прописан путь к старой.


Если есть возможность выслать проект или выложить куда-нибудь, я посмотрю.


Автор: Сергей_SU 6.11.2004, 13:33
Спасибо за ответ. Я выслал вам копию кода и необходимые прокси.
Заранее спасибо.

PS: Извиняюсь за вопрос, но что такое SCM. Я почему-то не встречался с таким понятием во время своего долгого изучения COM.

Автор: Fantasist 6.11.2004, 19:43
Цитата
Извиняюсь за вопрос, но что такое SCM


SCM - это Service Control Manager, в данном случае отвественный за связывание указателя на интерфейс с экземпляром объекта. CoGetClassObject - это обращение к SCM. Он будет пытаться загрузить объект и прокси, если необходимо.

Вот например:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnesscom/html/usingscm.asp

Автор: Fantasist 8.11.2004, 23:51
Посмотрел. Не запускается цикл выборки сообщений, соответсвенно сервер закрывается сразу после инициализации и запрос на создание объекта никогда не обрабатывается. Предлагаю заменить строчку Application.Run следующим кодом:

Код

 Terminated:=false;

 while not Terminated do
 begin
   if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
   begin
     if Msg.Message <> WM_QUIT then
        DispatchMessage(Msg);
     else
        Terminated:=true;
   end
   else
     WaitMessage;
 end;


P.S. К сожалению дома сейчас Делфи нет, так что пришлось ждать рабочего дня.

Автор: Сергей_SU 9.11.2004, 17:51
Огромное спасибо!!!

Сегодня или завтра обязательно попробую.

Однако ж это вызывает удивление - почему Delphi сама так не делает? Всяких wizard'ов наделали, а вот здесь приходиться ручками. Причем проблема не такая уж и явная, я лично сам вряд ли бы догадался.

Кстати, если не сложно, как Вы нашли ошибку? Или просто на базе своих знаний сразу определили проблему?

Еще раз спасибо!!!!

Автор: Fantasist 9.11.2004, 20:16
Цитата
Однако ж это вызывает удивление - почему Delphi сама так не делает?


На мой взгляд, Делфи, не смотря на многие достоинства, не очень оптимизированна под создание некоторых вещей. Например такого визарда как создание COM local server я там не нашел. То есть добавление сервера происходит к основному проекту, который, как считает Делфи, укладывается в основную логику. Основная логика в Делфи, как известно, это приложение центром которого является форма и компоненты к ней.


Цитата
Кстати, если не сложно, как Вы нашли ошибку? Или просто на базе своих знаний сразу определили проблему?


Запустил проект - закрывается сразу. Поставил бряк, запустил - оказываеться закрывается прямо в Application.Initialize. Удивился, прошелся по нутрям этого метода - дошло что в параметре запуска стоит /regserver. Убрал параметр. Запустил... Закрывается сразу. Но уже после выполнения Application.Run. Залез внутрь Run - очевидно, что не запускаеться цикл, потому что нет основной формы. Создал форму - все запустилось и работает, клиент способен создать сервер, только лишняя форма мелькает. Ну а дальше понятно. Вот теперь есть соответсвующие знания, а значит в следующий раз сразу пойму в чем дело. Делфи я редко использую для создания COM серверов, то есть опыта у меня в этом не так много.

P.S. То, что цикл выборки сообщений нужен, и то что в Делфи он обычно запускаеться вызовом Application.Run, факт, думаю, общеизвестный.


Автор: Сергей_SU 11.11.2004, 12:15
Все ОК!!!!!!!!

Вы мне очень помогли. Еще раз спасибо!

PS: идея добавить форму - просто класс. Жаль , что сам не догадался, а ведь действительно локальный COM сервер создаеться в дельфях внутри приложения, где, как думает делфи, должна быть форма.

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