Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.10.02;
Скачать: CL | DM;

Вниз

COM. Правильная инициализация/закрытие   Найти похожие ветки 

 
_VaaL_   (2003-09-12 10:19) [0]

Где правильно прописывать методы инициализации/закрытия при создании COM компонента? Не хотелось бы вызывать дополнительные собственные методы Init и Close. Хотелось бы чтобы при создании обьекта он сам себя инициализировал. Какие методы перекрывать / куда что дописывать? (Instancing - Multiple instance, Threading Model - Single).
Спасибо


 
Nikolay M. ©   (2003-09-12 10:28) [1]

Мнээ...
Секции initialization/finalization не подходят?


 
_VaaL_   (2003-09-12 10:38) [2]

А это будет правильно?
DllGetClassObject, DllCanUnloadNow, DllRegisterServer, DllUnregisterServer - то функции которые нужны для работы обьекта. Насколько я понимаю обект еще не создан когда библиотека загружена. Обьект создает TAutoObjectFactory.
Насколько я понимаю поочередность загрузки такова:
1. Загружается DLL
2. INITIALIZATION
3. TAutoObjectFactory.Create

Выгрузка:

1. Освобождение Обьекта.
2. FINALIZATION.

Если я прав то initialization/finalization не подходят, если нет - буду рад если меня поправят.


 
_VaaL_   (2003-09-12 11:49) [3]

Оказывается, если использовать разделы initialization/finalization, то компиляция проэкта проходит без проблем, а вот регистрация - вылетает. Посему вопрос появляется еще один - почему?


 
icWasya ©   (2003-09-12 12:10) [4]

а что значит - сам себя инициализировал?
вообще говоря есть метод Initialize - именно он вызывается при создании COM объекта. а для уничтожения - обычный Destroy
или надо что-то ещё ??


 
_VaaL_   (2003-09-12 12:14) [5]

Тоесть для инициации моих переменных мен нужно перекрыть Initialize и Destroy? Счас попробую...


 
icWasya ©   (2003-09-12 12:18) [6]

и не забывай про inherited


 
_VaaL_   (2003-09-12 12:26) [7]

procedure TСlassName.Initialize;
begin
inherited Initialize;
MyUnit.Init;
end;

Destructor TСlassName.Destroy;
begin
MyUnit.Quit;
inherited Destroy;
end;

Пишет Catastrophic Failure :(


 
_VaaL_   (2003-09-12 12:33) [8]

Теперь этот обьект даже создаватся нормально не может. Очень неохота выводить процедуры инициализации/закрытия в отдельные методы COM обьекта.
Идеальный вариант:
x:=CreateComObject(CLASS_Blablabla) as IBlablabla; // все уже инициировано можна приступать к работе
....
x:=NIL; // обьект освобожден, память под переменные - тоже


еще добавлю что процедуры моего модуля стопроцентно рабочие так как тестировались в отдельном проэкте.


 
Юрий Федоров ©   (2003-09-12 12:40) [9]

>>procedure TСlassName.Initialize;

override не забыл ?
Если не забыл, то написано все правильно


 
_VaaL_   (2003-09-12 12:52) [10]

>>Юрий Федоров ©
>>override не забыл ?
Не забыл.

Нащет перекрытия Initialize - это стандартный прием в COM-програмировании или просто совет навскидку?


 
icWasya ©   (2003-09-12 13:08) [11]

совет на основе личного опыта и анализа исходников VCL
а по-подробнее, что именно делается в MyUnit.Init ??


 
_VaaL_   (2003-09-12 13:19) [12]

В MyUnit.Init создается обект DOMDocument для загрузки определенных данных в динамический массив из XML документа.

var
XML: Variant;
...
XML:=CreateOLEObject("Msxml2.DOMDocument");
XML.Async:=false;
XML.Load(s);
...
Загрузка данных в динамический массив
...
XML:=varNULL; //освобождение обьекта DOMDocument


После этого массив сортируется для более быстрого поиска. Вот и все.

Еще одна процедура освобождает память динамического массива и должна вызыватся в конце.

Вот терерь это все нада всунуть в разделы инициализации/освобождения COM обьекта.


 
Юрий Федоров ©   (2003-09-12 13:35) [13]

MyUnit.Init, вызванный сам по себе (не в инициализации COM-объекта), не приводит к падению?
Если так, то возможно собака порылась где-то в CoInitFlags


 
_VaaL_   (2003-09-12 13:46) [14]

Нет, не приводит. Я модуль MyUnit тестировал в отдельном приложении до токо как писать COM обьект.
Фабрика класов создает мой обьект так :

TAutoObjectFactory.Create(ComServer, TMyCOMComponent, Class_Blablabla, ciMultiInstance, tmSingle);

Может я использую неправильную модель? (хотя врядли..). Поидее CoInitFlags устанавливается в зависимости именно от этой команды (так хелп говорит).


 
_VaaL_   (2003-09-12 15:24) [15]

А в ответ тишина... :)


 
Nikolay M. ©   (2003-09-12 15:56) [16]


> var
> XML: Variant;

- глобальная переменная или она принадлежит СОМ-объекту?
Если первое, то хочется напомнить свой первый пост :)
Если второе - то будет ли происходить Catastrophic failure, если закомментировать MyUnit.Init/MyUnit.Quit?


 
nikkie ©   (2003-09-12 15:57) [17]

ты вызов своего Init поставь под try...except


 
Юрий Федоров ©   (2003-09-12 15:59) [18]

кроме того
1. Создается ли COM-объект (я так понял, что имеем дело с InProc Server) в основном потоке приложения или в дополниьельном.
2. С какими параметрами происходит вызов CoInintializaEx в вызывающем приложении (для этого потока)


 
_VaaL_   (2003-09-12 16:16) [19]

XML - локальная перменная процедуры Init. Тоесть первое отпадает. А вот второе - ничего непадает, если обьект не инициализируется в методе Initialize, хотя если запускать в другом проэкте то процедура Init работает нормально... странно.


 
_VaaL_   (2003-09-12 16:23) [20]

Я закоментировал секцию работы с XML - инициация прошла успешно (покрайней мере без видиміх проблем). Значит я неправильно работаю с XML. Выше я приводил пример инициации COM обьекта DOMDocument. Я что, создаю/удаляю его неправильно?
var
XML: Variant;
...
XML:=CreateOLEObject("Msxml2.DOMDocument");
XML.Async:=false;
XML.Load(<filename>);
...
XML:=varNULL;


 
Polevi ©   (2003-09-12 16:27) [21]

>_VaaL_ (12.09.03 16:23) [20]
возможно плохой xml документ, парсер предоставляет информацию об ошибках парсинга, проверь


 
Юрий Федоров ©   (2003-09-12 16:29) [22]

Отладчик не работает?
Какой-то Exception поднимается при работе с XML, только и всего. Если узнать, какой именно - все сразу станет ясно


 
Nikolay M. ©   (2003-09-12 16:30) [23]

А в коде выше еще написана какая-то "Загрузка данных в динамический массив" - там что?


 
_VaaL_   (2003-09-12 16:38) [24]

>>Юрий Федоров © (12.09.03 16:29) [22]
Отладчик не работает?
Да в том то и дело что при использовании в любом другом проекте ексепшенов нету :(. А как я могу отладить DLL пошагово? - вроде никак. :(

Nikolay M. © (12.09.03 16:30) [23]
А в коде выше еще написана какая-то "Загрузка данных в динамический массив" - там что?

Простой разбор XML, установка размера для динамического массива и заполнение данными из XML документа


 
_VaaL_   (2003-09-12 16:43) [25]

Polevi © (12.09.03 16:27) [21]
не может он быть ошибочным так как открывается через експлорер. DTD схем нету.


 
Nikolay M. ©   (2003-09-12 16:55) [26]


> Простой разбор XML, установка размера для динамического
> массива и заполнение данными из XML документа

А если это все закомментировать?
Если все ок, тогда правы

> Polevi © (12.09.03 16:27) [21]
> Юрий Федоров © (12.09.03 16:29) [22]


 
_VaaL_   (2003-09-12 16:59) [27]

Nikolay M. © (12.09.03 16:55) [26]
Я коментировал. И все работало хорошо. Но тогда почему та же процедура без проблем работает в отдельном проэкте (никаких ексепшенов)?


 
Nikolay M. ©   (2003-09-12 17:07) [28]

А код большой?
Кинь сюда, неохота на кофейной гуще гадать :)


 
_VaaL_   (2003-09-12 17:21) [29]


type
TStoredProc = record
Name: string;
Params: array of string;
Request: string;
end;
var
SP: array of TStoredProc;
....
....
XML:=CreateOLEObject("Msxml2.DOMDocument");
XML.Async:=false;
XML.Load(s);
Root:=XML.DocumentElement;
if Root.HasChildNodes then
begin
Count:=Root.ChildNodes.Length;
SetLength(SP, Count);
for i:=0 to Root.ChildNodes.Length - 1 do
begin
SPNode:=Root.ChildNodes.Item(i);
SP[i].Name:=SPNode.NodeName; // Getting Name
SPParams:=SPNode.ChildNodes.Item(0); // Getting Parameters
if SPParams.HasChildNodes then
begin
Count:=SPParams.ChildNodes.Length;
SetLength(SP[i].Params, Count);
for j:=0 to SPParams.ChildNodes.Length - 1 do
begin
SPPar:=SPParams.ChildNodes.Item(j);
SP[i].Params[j]:=SPPar.NodeName;
end;
end;
SPParams:=SPNode.ChildNodes.Item(1); // Getting Request
SPPar:=SPParams.ChildNodes.Item(0);
if SPPar.NodeType = 4 /*CDATA*/ then
SP[i].Request:=SPPar.NodeValue;
end;
end;
XML:=varNULL; // Closing XML Object


Здесь:
XML, Root, SPNode, SPPar: Variant;
SP - структура которая заполняется из XML

Пример XML:
<?xml version="1.0" encoding="utf-8"?>
<root>
<test>
<params>
<id/>
<name/>
</params>
<request>
<![CDATA[Select <[name]> from Main_Menu where mm_id=<[id]>;]]>
</request>
</test>
</root>


 
Nikolay M. ©   (2003-09-12 17:25) [30]

Хм. Сразу бросается в глаза, что TStoredProc - имя уже объявленного класса в DBTables... Этот модуль нигде не подключается?


 
_VaaL_   (2003-09-12 17:27) [31]

Nikolay M. © (12.09.03 17:25) [30] нет. Здесь вообще нет подключения к какой бы то нибыло БД


 
Erik   (2003-09-12 18:13) [32]

"А как я могу отладить DLL пошагово? - вроде никак. :("
Если это без проблем отлаживается! Идем в Run/Parametrs
Там заполняем Host Application - кот вызывает твою dll.
И отлаживай себе на здорове. Но если проблема серездная, то врядли тебе здесь ответят. Com вобще дело темное.


 
Юрий Федоров ©   (2003-09-12 18:13) [33]

Насчет отладчика - можно отлаживать DLL без проблем.
после помещения Exe и DLL в одну группу проектов и перебилда обоих отладчик ходит насквозь...
я на 90 процентов уверен, что дело в каком-то конфликте, связанном с флагами инициализации COM (конфликт поточных моделей).
Ты не пробовал поставить ThreadingModel = tmApartment?

В общем, один запуск прорраммы подл отладчиком - и ответ на вопрос будет получен...


 
Serginio666   (2003-09-12 18:55) [34]

Помоему сам нарывался на ThreadingModel = tmApartment. Работает только в TComponentFactory. Да и для DLL это не играет роли если не нужен маршалинг.
Лучше поставь проинициализируй как MTA, т.к. c STA куча проблем.


 
Юрий Федоров ©   (2003-09-12 19:04) [35]

>>Serginio666 (12.09.03 18:55) [34]
С апартаментами проблемы только с Local Server, с InProc все должно быть нормально.
Да и лечится легко, путем небольшого потомка от фабрики классов...


 
Serginio666   (2003-09-12 19:25) [36]

Это я знаю, сам создавал,проверял. Да и для Inproc сервера ThreadingModel = tmApartment не играет никакой роли без TApartmentThread передается прямая ссылка на объект.
Может проблема в
http://www.rsdn.ru/article/atl/atlsingleton.xml

"Проблема маршалинга синглтона в фабрике классов также весьма актуальна для внутрипроцессных серверов, так как клиенты запросто могут находиться в разных апартаментах, и все клиенты будут получать прямую ссылку на синглтон. Для синглтонов с потоковой моделью Apartment это может означать, что вызовы могут приходить из других потоков. Без синхронизации все закончится плачевно, а клиенты даже не будут ничего подозревать, так как имеют дело не с proxy, а с прямым указателем, и ошибку RPC_E_WRONGTHREAD, означающую, что вызов был сделан из “неподходящего” потока, им никто не вернет."


 
Serginio666   (2003-09-12 19:52) [37]

Да еще очень плохо работать в СОМ с глобальными переменными.
Разве нельзя
Внести все в объект и работать с полем объекта.
procedure TСlassName.Initialize;
begin
inherited Initialize;
XML:=CreateOLEObject("Msxml2.DOMDocument");
end;

Destructor не нужен.


 
_VaaL_   (2003-09-17 13:51) [38]

Короче, помудрил я и понял, что всетаки проблема тут в создании Msxml2.DOMDocument такое впечатление что когда я вызываю CreateOLEObject("Msxml2.DOMDocument") то еще небыла вызывана CoInintialize, хотя модуль ComObj стоит в Uses...
Поэтому решил хранить загружаемые данные в простых файлах. После этого все начало работать без проблем.
Спасибо всем кто помогал разбиратся с этим делом.


 
Erik   (2003-09-18 14:37) [39]

А я то думаю, чего у меня глючит завершение InProc сервера! ThreadingModel = tmApartment стоит хотел поменять да так и оставил. А маршалинг у меня есть и выгружается коректно только в случаее с Exe сервером.



Страницы: 1 вся ветка

Текущий архив: 2003.10.02;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.016 c
4-4163
Dude
2003-07-29 17:57
2003.10.02
Послать Shortcut


1-3905
webpauk
2003-09-22 13:02
2003.10.02
Изменение св-в компонента


1-3908
voprosik
2003-09-22 08:51
2003.10.02
Список польз-лей, открывших файл в сети


1-3945
Goshi
2003-09-20 00:18
2003.10.02
Как отловить завершение работы программы через ShellExecute


3-3756
diokant
2003-09-12 10:46
2003.10.02
Как в MS SQL, зная имя таблицы, получить список ее полей?