Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как правильно зарегить плагин к 1С ? [D7, XP]


Страницы:   1 2

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

Ничего не понимаю - что я делаю не так ?


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо