![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как правильно зарегить плагин к 1С ? [D7, XP]
ANB © (2006-04-12 17:45:00)На основе заготовки MASTER и SAMPLE ничего не работало.
Взял SAMPLE2 (который ролики крутит), переделал для себя - работает.
Запустил на другом компе - не находит CLSID.
Все понятно - не зарегился COM сервер.
Снес у себя ветки в реестре - воспризвел ошибку.
Начал ломать кусочками.
Исправил GUID класса TAddInVideo - работает.
Снес проигрыватель и все, что его касается - работает.
Изменяю строку :
initialization
TComObjectFactory.Create(ComServer, TAddInOfficeReport, Class_AddInOfficeReport,
'AddInVideo', '', ciMultiInstance, tmApartment);
на на
TComObjectFactory.Create(ComServer, TAddInOfficeReport, Class_AddInOfficeReport,
'AddInMyPluggin', '', ciMultiInstance, tmApartment);
еще работает, но если после этого сменить GUID - вопит, что нет интерфейса IInitDone.
Меняю GUID, ставлю на место AddInVideo - снова все работает.
Вывод - где то ломаю регистрацию. Еще зачем то тащится форма AddInDoc, которая мне совсем не нужна (со своей регистрацией и TLB).
Кто знает - какие минимальные телодвижения нужно сделать, чтобы плагин в 1С нормально регистрился и загружался ?
ANB (2006-04-18 12:25:00) [1]
> tesseract © (18.04.06 09:55) [26]
Просто нулл не помогал.
Короче - вот так работает :
Application_1C : Variant;
....
try
Application_1C := Null;
Application_1C := Variant(pConnect).AppDispatch;
// pConnect я заранее сохранил в Init как IDispatch
IDispatch(Application_1C)._AddRef;
....
finally
Application_1C := Null;
end;
Методы Init и Done такие :
function TAddInObject.Init(pConnection : IDispatch): HResult; stdcall;
var iRes : Integer;
begin
pConnect := pConnection;
pErrorLog := nil;
pConnect.QueryInterface(IID_IErrorLog,pErrorLog);
pEvent := nil;
pConnect.QueryInterface(IID_IAsyncEvent,pEvent);
pProfile := nil;
iRes := pConnect.QueryInterface(IID_IPropertyProfile,pProfile);
if (iRes = S_OK) then
begin
pProfile.RegisterProfileAs('OfficeReport_Profile');
if (LoadProperties() <> True) then
begin
Init := E_FAIL;
Exit;
end;
end;
pStatusLine := nil;
pConnect.QueryInterface(IID_IStatusLine,pStatusLine);
Init := S_OK;
end;
function TAddInObject.Done: HResult; stdcall;
var n : Integer;
begin
SaveProperties();
if (pErrorLog <> nil) then begin
pErrorLog._Release();
pErrorLog := nil;
end;
if (pEvent <> nil) then begin
pEvent._Release();
pEvent := nil;
end;
if (pProfile <> nil) then begin
pProfile._Release();
pProfile := nil;
end;
if (pStatusLine <> nil) then begin
pStatusLine._Release();
pStatusLine := nil;
end;
if (pConnect <> nil) then begin
n := pConnect._Release();
pConnect := nil;
// ShowMessage('Done = ' + IntToStr(n));
if (n > 0) then begin
ShowMessage('Ошибка : Не произошло освобождение интерфейса 1С. Осталось ссылок : '
+ IntToStr(n));
end;
end;
Done := S_OK;
end;
Ну и Application_1C передаю внутрь своих процедур только по ссылке (через var).
tesseract (2006-04-18 09:55:00) [2]
> Кстати, как правильно достать и освободить AppDispatch ?
В смысле как избавится от интерфейса который тебе 1c вернул? в null его :-)
ANB (2006-04-17 17:41:00) [3]
> tesseract © (17.04.06 17:10) [23]
Кстати, как правильно достать и освободить AppDispatch ?
ANB (2006-04-17 17:40:00) [4]
> Не правильно задан DONE. Наверно не освободил какие-нибудь
> ресурсы.
Не. Это я в своем обработчике намутил, дергая AppDispatch. Надо разбираться и чинить.
Отключаешь - все работает как надо.
tesseract (2006-04-17 17:10:00) [5]
> Выслать рабочий код для анализа (для статьи) ?
У меня примеров ~ 10-20. рабочих :-)
> Единственное - таки нарвался на граблю, при которой 1С остается
> в списке задач.
Не правильно задан DONE. Наверно не освободил какие-нибудь ресурсы.
ANB (2006-04-17 16:37:00) [6]
> tesseract © (17.04.06 15:39) [20]
Выслать рабочий код для анализа (для статьи) ?
ANB (2006-04-17 16:37:00) [7]
> Сергей М. © (17.04.06 13:34) [19]
Не, примеров.
> tesseract © (17.04.06 15:39) [20]
Я вообще коментил все получение интерфейсов.
Короче, кое как получилось.
1. Взял рабочий плагин (был на работе)
2. Аккуратно вытер все чужое и добавил свое
3. Переименовал проект в имя плагина
4. Изменил имена плагина в 2-х местах - инициализации и RegisterExtensionAs
5. Изменил имя профиля
6. Сменил GUID
7. Скопировал под новым именем ресурс проекта и строку с ID 100 исправил на имя плагина.
8. Перекомпилял все
9. Почистил реестр (пришлось с утра прожку написать для почистки)
И все заработало. Сравнил работающий проект с примером 1С - разницы не нашел.
Единственное - таки нарвался на граблю, при которой 1С остается в списке задач.
tesseract (2006-04-17 15:39:00) [8]
> Помоги !!!
А в мэйл слабо????
iRes := pConnection.QueryInterface(IID_IPropertyProfile,pProfile);
if (iRes = S_OK) then
begin
pProfile.RegisterProfileAs(AddIn_Name + '_Profile');
if (LoadProperties() <> True) then
begin
Init := E_FAIL;
Exit;
end;
end;
Выруби это или хотя-бы E_FAIL не возвращай.
> Убил ветку AddIn.OfficeReport у себя на компе - тоже пошла
> ошибка "отсутствует CLSID"
Такое бывает при отсутсвии SetServerName. или id100.
Рабочий код инициализации:
ComServer.SetServerName('AddIn');
TComObjectFactory.Create(ComServer,tInterBase, Class_InterbaseAddin,
'InterBase', 'interbase addin class', ciSingleInstance, tmApartment);
Сергей М. (2006-04-17 13:34:00) [9]
> читал исходник
Неужели исходник 1С ?!
ANB (2006-04-17 12:05:00) [10]Внимательно читал исходник и трассировал выполнение - выяснил, что 1С сама не выполняет регистрацию. DLL регит сама себя при выполнении раздела инициализации.
ANB (2006-04-17 09:49:00) [11]
> tesseract © (13.04.06 10:39) [7]
Помоги !!!
ANB (2006-04-14 13:53:00) [12]Укоротил имя плагина - не помогло.
ANB (2006-04-14 12:21:00) [13]Убил дополнительно в реестре ветку с GUID плагина - вернуалсь первоначальная ситуация. Ща закиплю.
ANB (2006-04-14 11:30:00) [14]Убил ветку AddIn.OfficeReport у себя на компе - тоже пошла ошибка "отсутствует CLSID"
ANB (2006-04-14 11:29:00) [15]Такс. Попробовал запустить DLL на другом компе - срабатывает только раздел инициализации, потом ругнулась, что не найден интерфейс IInitDone. Убил ветку в реестре - начала ругаться, что не найден CLSID.
ANB (2006-04-14 11:14:00) [16]Раздел инициализации :
initialization
ShowMessage('Регистрация');
ComServer.SetServerName('AddIn');
TComObjectFactory.Create(ComServer,TAddInObject,CLSID_AddInObject,
AddIn_Name, 'V7 AddIn 2.0', ciMultiInstance);
end.
ANB (2006-04-14 11:13:00) [17]Метод GetInfo :
function TAddInObject.GetInfo(var pInfo: PSafeArray{(OleVariant)}): HResult; stdcall;
var varInfo : OleVariant;
begin
ShowMessage('GetInfo');
varInfo := '2000';
PutNParam(pInfo, 0, varInfo);
GetInfo := S_OK;
end;
ANB (2006-04-14 11:13:00) [18]Метод Init :
function TAddInObject.Init(pConnection: IDispatch): HResult; stdcall;
var iRes : Integer;
begin
ShowMessage('Init');
// pConnect := pConnection;
pErrorLog := nil;
pConnection.QueryInterface(IID_IErrorLog,pErrorLog);
pEvent := nil;
pConnection.QueryInterface(IID_IAsyncEvent,pEvent);
pProfile := nil;
iRes := pConnection.QueryInterface(IID_IPropertyProfile,pProfile);
if (iRes = S_OK) then
begin
pProfile.RegisterProfileAs(AddIn_Name + '_Profile');
if (LoadProperties() <> True) then
begin
Init := E_FAIL;
Exit;
end;
end;
pStatusLine := nil;
pConnection.QueryInterface(IID_IStatusLine,pStatusLine);
Init := S_OK;
end;
ANB (2006-04-14 11:12:00) [19]Постю куски исходника :
Объявление констант :
// Здесь нужно описать строки, которые станут рассширением языка в 1С
resourcestring
strWordReport = 'Word_Report,Отчет_В_Ворд';
const
// Этот GUID нужно обязательно перегенерить
CLSID_AddInObject : TGUID = '{E3FB6F4A-11AD-4B3C-954F-9EAA72B9D4D6}';
// В эту константу нужно записать имя плагина
// Проще, если оно будет совпадать с именем проекта
AddIn_Name = 'OfficeReport';
// Это же имя нужно еще записать в ресурс проекта в строку с ID = 100.
type
// Номера свойств
TProperties = ( LastProp );
// Номера методов
TMethods = ( methWordReport, LastMethod );
ANB (2006-04-14 11:08:00) [20]
> tesseract © (13.04.06 10:39) [7]
Текс. Собрал всю доку, плюс эту рекомендацию.
Взял пустой шаблон MASTER и начал делать.
Что сделал :
1. Сохранил проект под новым именем
2. Это же имя объявил константой.
3. Заменил GUID в unit PropPage
4. Заменил GUID в unit AddInObj;
5. Запихнул константу с именем в :
- раздел initialization
- метод RegisterExtensionAs
- метод Init в регистрацию профиля (ничего про него не понял)
6. В ресурс проекта добавил строку с ID = 100 и именем проекта.
Исходники запостю ниже.
Что получил :
В 1С вызываю :
Файл_Компоненты = "OfficeReport.dll";
Сообщить (Файл_Компоненты);
Если ЗагрузитьВнешнююКомпоненту(Файл_Компоненты) = 0 Тогда
Сообщить("ошибка загрузки");
Возврат;
КонецЕсли;
По всем методам плагина повтыкал отладочные сообщения (отладчик потом подрублю, когда надо будет логику отлаживать).
Вижу :
1. Вызван раздел инициализации (прошла регистрация, в нем менял имя в
TComObjectFactory.Create(ComServer,TAddInObject,CLSID_AddInObject,)
AddIn_Name, 'V7 AddIn 2.0', ciMultiInstance);
2. Вызван Init (в нем менял только имя профиля)
3. Вызван GetInfo (только вставил ShowMessage)
4. Вызван Done
1С вываливает ошибку :
Ошибка при инициализации объекта из компоненты C:\Program Files\1Cv77\1SBDemo\OfficeReport.dll
Ничего не понимаю - что я делаю не так ?