Модераторы: MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> как получить коллекцию от add-in-а? возврат коллекции реализованной в add-in 
V
    Опции темы
aleksh
Дата 7.10.2010, 17:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 609
Регистрация: 8.7.2008

Репутация: нет
Всего: 13



что нужно указать у метода интерфейса add-in outlook-а, чтобы он вернул экземпляр реализованной в этом самом add-in-е коллекции?
PM MAIL   Вверх
cat512
Дата 7.10.2010, 17:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 438
Регистрация: 20.3.2007

Репутация: 3
Всего: 15



добавь в TLB, описание интерфейса, возвращающего Enumerator.
PM MAIL   Вверх
aleksh
Дата 8.10.2010, 00:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 609
Регистрация: 8.7.2008

Репутация: нет
Всего: 13



с enumerator-ами не знаком...


cat512, посоветуй, как лучше получить из add-in-а коллекцию контактов из адресной книги?
PM MAIL   Вверх
cat512
Дата 8.10.2010, 10:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 438
Регистрация: 20.3.2007

Репутация: 3
Всего: 15



Цитата(aleksh @ 8.10.2010,  00:32)
с enumerator-ами не знаком...


cat512, посоветуй, как лучше получить из add-in-а коллекцию контактов из адресной книги?

Выложи хоть TLB, что ли. 
PM MAIL   Вверх
aleksh
Дата 8.10.2010, 14:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 609
Регистрация: 8.7.2008

Репутация: нет
Всего: 13



Цитата(cat512 @  8.10.2010,  10:12 Найти цитируемый пост)
Выложи хоть TLB, что ли.  

так он еще в процессе написания, так что выкладывать нечего


cat512, приведи, пожалуйста, простой пример работы с enumeration
как заполнять, как принимать, как считывать, в общем - как работать с ним
PM MAIL   Вверх
cat512
Дата 8.10.2010, 17:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 438
Регистрация: 20.3.2007

Репутация: 3
Всего: 15



Это сложно, ок, пороюсь в своих исходниках на выходных, выложу тебе какой нить примерчик
PM MAIL   Вверх
aleksh
Дата 8.10.2010, 19:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 609
Регистрация: 8.7.2008

Репутация: нет
Всего: 13



cat512, взгляни - это add-in, вот только он чего-то не работает. не присваиваются значения outlook и namespace - можешь подсказать где ошибка?
Код

unit uAddin;

interface

uses
  Classes, Windows, ComObj, ActiveX, ABOutlook_TLB, StdVcl, Registry,
  Variants, sysutils, dialogs,
  AddInDesignerObjects_TLB, Outlook_TLB, office_tlb;

type

  TABFactory = class(TAutoObjectFactory)
  public
    procedure UpdateRegistry(Register: Boolean); override;
  end;

  TAB = class(TAutoObject, IAB, _IDTExtensibility2)
  private
    outlook, namespace, cfolder: OleVariant;
  protected
    function CountOfBooks: Integer; safecall;
    function NameOfBooks(index: Integer): WideString; safecall;
    function CountOfContacts(const name: WideString): Integer; safecall;
    function FieldOfContacts(const book: WideString; index,
      field: Integer): WideString; safecall;
    function Test: WideString; safecall;
    { Protected declarations }
  public
    procedure OnConnection(const Application: IDispatch; ConnectMode: ext_ConnectMode;
                           const AddInInst: IDispatch; var custom: PSafeArray); safecall;
    procedure OnDisconnection(RemoveMode: ext_DisconnectMode; var custom: PSafeArray); safecall;
    procedure OnAddInsUpdate(var custom: PSafeArray); safecall;
    procedure OnStartupComplete(var custom: PSafeArray); safecall;
    procedure OnBeginShutdown(var custom: PSafeArray); safecall;
  end;

implementation

uses ComServ;

{ TAdFactory }

procedure TABFactory.UpdateRegistry(Register: Boolean);
var Reg:TRegistry;
begin
  inherited;
  Reg:=TRegistry.Create;
  try
    Reg.RootKey:=HKEY_LOCAL_MACHINE;
    if Register then
      begin
        if Reg.OpenKey('Software\Microsoft\Office\Outlook\Addins\'+GetProgID, TRUE) then
          Reg.WriteInteger('LoadBehavior', 3);
      end
    else
      if Reg.KeyExists('Software\Microsoft\Office\Outlook\Addins\'+GetProgID) then
        Reg.DeleteKey('Software\Microsoft\Office\Outlook\Addins\'+GetProgID);
  finally
    Reg.Free;
  end;
end;

{ TAd }

procedure TAB.OnAddInsUpdate(var custom: PSafeArray);
begin
end;

procedure TAB.OnBeginShutdown(var custom: PSafeArray);
begin
end;

procedure TAB.OnConnection(const Application: IDispatch;
  ConnectMode: ext_ConnectMode; const AddInInst: IDispatch;
  var custom: PSafeArray);
begin
outlook := application;
end;

procedure TAB.OnDisconnection(RemoveMode: ext_DisconnectMode;
  var custom: PSafeArray);
begin
cfolder := unassigned;
namespace := unassigned;
outlook := unassigned;
end;


procedure TAB.OnStartupComplete(var custom: PSafeArray);
begin
end;

function TAB.CountOfBooks: Integer;
var
  I: Integer;
begin
namespace := outlook.getnamespace('MAPI');
cfolder := namespace.getdefaultfolder(olfoldercontacts);
result := 1;

for I := 1 to cfolder.folders.count do
  inc(result);
end;

function TAB.NameOfBooks(index: Integer): WideString;
begin
namespace := outlook.getnamespace('MAPI');
cfolder := namespace.getdefaultfolder(olfoldercontacts);

if index = 1 then
  result := cfolder.name
else
  if (index > 1) and (index <= cfolder.folders.count) then
    result := cfolder.item[index].name
  else
    result := '';
end;

function TAB.CountOfContacts(const name: WideString): Integer;
begin
namespace := outlook.getnamespace('MAPI');
cfolder := namespace.getdefaultfolder(olfoldercontacts);
if name = cfolder.name then
  result := cfolder.items.count
else
  try
    result := cfolder.folders(name).items.count;
  except
    result := 0;
  end;
end;

function TAB.FieldOfContacts(const book: WideString; index,
  field: Integer): WideString;
var
  adrbook: variant;
begin
namespace := outlook.getnamespace('MAPI');
cfolder := namespace.getdefaultfolder(olfoldercontacts);
if (book = cfolder.name) then
  begin
    if (index <= cfolder.items.count) and (index > 0) then
      begin
        case field of
          0 : result := cfolder.items.item[index].fullname;
          1 : result := cfolder.items.item[index].email1address;
          2 : result := cfolder.items.item[index].businessfaxnumber;
        else
          result := '';
        end
      end
    else
      result := '';
  end
else
  begin
    try
      adrbook := cfolder.folders(book);
      if (index <= adrbook.items.count) and (index > 0) then
        begin
          case field of
            0 : result := cfolder.items.item[index].fullname;
            1 : result := cfolder.items.item[index].email1address;
            2 : result := cfolder.items.item[index].businessfaxnumber;
          else
            result := '';
          end
        end
      else
        result := '';
    except
      result := '';
    end;
  end;
end;

function TAB.Test: WideString;
begin
result := 'test complite';
end;

initialization
  TABFactory.Create(ComServer, TAB, Class_AB, ciMultiInstance, tmApartment);
end.

PM MAIL   Вверх
cat512
Дата 9.10.2010, 14:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 438
Регистрация: 20.3.2007

Репутация: 3
Всего: 15



фигня какая - то.
Есть то, что нe нужно и нет того, что нужно.
Вот на это мне надо посмотреть - AddInDesignerObjects_TLB.
Ты пробовал писать простенкий com-server? Если нет, то советую тебе сначала написать
простенький примерчик, в котором бы использовался 1 или 2 метода, считывания/установки значений объекта.
Это для того что-бы ты почувствовал, какие механизмы VCL использует для работы с COM.
Просто задача за которую ты взялся - нетривиальная. Неимея определённых навыков, сложно будет получить нужный результат.

Я набросал простенький примерчик использования Enumerator-а(см. аттач). 
Посмотри его (Не забудь зарегистр. библиотеку), затем
напиши мне каким образом, твой аддин будет взаимодействовать с Outlook (
Как будет коннектиться? 
Будет ли создавать экземпляр Outlook-а? 
Знает ли что-нибудь Outlook о твоём аддине?
Если знает, то какие методы используются для взаимодействия?
Какие методы планируешь реализовать для экспорта данных?
)
и возможно (если задача имеет решение) тогда я подскажу тебе, как это белее менее правильно сделать.

Присоединённый файл ( Кол-во скачиваний: 8 )
Присоединённый файл  TestComEnumerator.rar 244,76 Kb
PM MAIL   Вверх
aleksh
Дата 11.10.2010, 13:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 609
Регистрация: 8.7.2008

Репутация: нет
Всего: 13



Цитата(cat512 @  9.10.2010,  14:29 Найти цитируемый пост)
фигня какая - то.
Есть то, что нe нужно и нет того, что нужно.

не спорю
Цитата(cat512 @  9.10.2010,  14:29 Найти цитируемый пост)
Неимея определённых навыков, сложно будет получить нужный результат.

навыкав нет, но результат нужен

задача следуюшая - поскольку оутлук при параноидальных настройках спрашивает о доступе при каждом обращении надо написать адд-ин, который один раз получает разрешение на работу (при запуске оутлука), подключается к запущенной копии и дает возможность сторонней программе получать данные о контактах

адд-ины до этого не писал, посему такае ерунда и получается

буду признателен за любой совет, который поможет реализовать описанную задачу
PM MAIL   Вверх
cat512
Дата 12.10.2010, 16:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 438
Регистрация: 20.3.2007

Репутация: 3
Всего: 15



Цитата(aleksh @ 11.10.2010,  13:19)
Цитата(cat512 @  9.10.2010,  14:29 Найти цитируемый пост)
фигня какая - то.
Есть то, что нe нужно и нет того, что нужно.

не спорю
Цитата(cat512 @  9.10.2010,  14:29 Найти цитируемый пост)
Неимея определённых навыков, сложно будет получить нужный результат.

навыкав нет, но результат нужен

задача следуюшая - поскольку оутлук при параноидальных настройках спрашивает о доступе при каждом обращении надо написать адд-ин, который один раз получает разрешение на работу (при запуске оутлука), подключается к запущенной копии и дает возможность сторонней программе получать данные о контактах

адд-ины до этого не писал, посему такае ерунда и получается

буду признателен за любой совет, который поможет реализовать описанную задачу

Привет, разбирался утром с твоей темой, хочу сказать что, ты в принципе мыслил в правильном напрвлении( подключил нужные описания интерфейсов и написал логичный код, поэтому забираю свои слова обратно smile), за исключением одного: в твоём варианте,
тебе надо писать внепроцеснный ком-серверб либо использовать моникер. smile Как раз Поэтому, у тебя не запоминались интерфейсы оутлука в локальных переменных.

Это сообщение отредактировал(а) cat512 - 12.10.2010, 16:55
PM MAIL   Вверх
aleksh
Дата 12.10.2010, 17:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 609
Регистрация: 8.7.2008

Репутация: нет
Всего: 13



проблема почти решена, в сторонней программе создаю объект адд-ина, но вот только при чтении email параноидальные настройки оутлука все же просыпаются (при обращении из длл-ки)

можно это как-то обойти?

Цитата(cat512 @  12.10.2010,  16:13 Найти цитируемый пост)
внепроцеснный ком-серверб либо использовать моникер

а что значит внепроцеснный и моникер?
PM MAIL   Вверх
aleksh
Дата 12.10.2010, 18:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 609
Регистрация: 8.7.2008

Репутация: нет
Всего: 13



почитал про моникеры - пока мало что понял, но это пройдет

возникает вопрос - предположим при запуске соглашаемся на запуск адд-ин-а, он получает данные из адресной книги, мы потом получаем из сторонней программы эти данные. но как быть с обновлением этих данных. моникер позволит заново выполнить метот адд-ин-а и при этом помнить что он разрешен?
PM MAIL   Вверх
cat512
Дата 12.10.2010, 22:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 438
Регистрация: 20.3.2007

Репутация: 3
Всего: 15



Цитата(aleksh @ 12.10.2010,  18:24)
почитал про моникеры - пока мало что понял, но это пройдет

возникает вопрос - предположим при запуске соглашаемся на запуск адд-ин-а, он получает данные из адресной книги, мы потом получаем из сторонней программы эти данные. но как быть с обновлением этих данных. моникер позволит заново выполнить метот адд-ин-а и при этом помнить что он разрешен?

Честно говоря не совсем понял что-за проблема с настройками, ну да ладно, объясню суть почему не подходит обычная реализация inproc(внутрипроцессного) - сервера.
Дело в том что при обычной реализации внутрипроцессного сервера, ты в каждом новом процессе, использующем твой Addin, будешь использовать разделяемый образ кода dll Addina, и отдельную секцию(копию) данных для каждого процесса (если точнее то твои сом объекты создают. в куче).
Если рассматривать приведённый тобой код, то получалась след. картина:
При запуске оутлука, последний загружал addin в адресное пространство, создавал объект в своей секции данных, честно передавал указатель на интерфейс твоему объекту, и завершал свою инициализацию. Затем ты в своей программе, в которую хотел экспортировать данные, выполнял те же действия по загрузке addin-а и созданию объекта, но при этом, у тебя создавался новый экземпляр
объекта со своими не инициализированными полями outlook, namespace и т.д.(причём первый объект был инициализирован честно). Т.е. другими, словами у тебя не шарились данные между объектами.
Не знаю каким образом ты "почти решил задачу", потому как это проблема всех внутрипроцессных серверов, но если действительно решил, то буду благодарен, если расскажешь.
Теперь подумаем как же можно решить проблемму шаринга данных, если она осталась актуальной. 
Лично я вижу два варианта: Внепроцессный (Local) exe сервер и создание Моникера.
Exe - сервер, одназначно решает проблему шаринга данных. Но я не уверен, могут ли использоваться Exe - сервера в качестве аддинов для офиса. Предполагаю что могут, но это надо проверить.
Моникер - это по сути указатель на реально сущ. com-объект, т.е. при использовании интерфейсов моникера, можно получить указатель на интерфейс того самого "честно инициализированного" объекта в аддресном пространстве outlooka. Но тут надо "поиграться", прежде чем получить реально работающий код. 
Цитата

но как быть с обновлением этих данных

Хороший вопрос smile. Вот они, проблемки,  полезли smile А я тебе говорил - нетривиальная задачка. smile
Вообщем с этим не так страшно как кажется.
Надо просто в com-сервере реализовать интерфейс IConnectionPoint, а для этого в мастере создания Automation object, включить флажок  Generate Event Support code.
Поддержка этого интерфейса, активирует механизм Call-back вызовов, регистрируемых клиентом на сервере. Таким образом ты можешь дёргать клиента, при обновлении данных в оутлуке 


Это сообщение отредактировал(а) cat512 - 12.10.2010, 23:24
PM MAIL   Вверх
aleksh
Дата 13.10.2010, 13:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 609
Регистрация: 8.7.2008

Репутация: нет
Всего: 13



Цитата(cat512 @  12.10.2010,  22:45 Найти цитируемый пост)
Если рассматривать приведённый тобой код, то получалась след. картина:

это уже понял, поэтому "почти решенние" было банальным до не приличия - подключался к запущенному outlook-у и соответсвенно иницилизирован все что надо. но вот в чем сложность - при уже упомянутых "параноидальных" настройках outlook-а при попытке прочитать email (именно его, с остальными полями таких осложнений нет) появляется окно, в котором спрашивается разрешение на чтение этих данных, ведь работа именно этого экземпляра аддина не была разрешена (при внутренней работе аддина - когда запускается outlook дается разрешение на включения аддина и он все данные собирает без всяких разрешений)

все осложняется тем, что это мой первый подход к таким задачам, в связи с этим возникают вопросы - нужно настраивать моникер (реализовывать его интерфейс) в самом аддине, или просто пробегать по таблице с поиском progid? и какие заголовочные файлы нужны для работы моникеров?


cat512, напишу большое спасибо (и вообще буду крайне признателен) если выложишь простой пример работы моникера (чтобы суть уловил)

и еще - при использовании моникера - при вызове методов будет дергаться запущенный экземпляр (на сколько понимаю да, но решил что лучше уточнить)?
PM MAIL   Вверх
cat512
Дата 13.10.2010, 17:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 438
Регистрация: 20.3.2007

Репутация: 3
Всего: 15



так, набросал код с Моникером, вроде работает.

Код

//Регистрация в Rot
procedure TOutlookGrabber.ConnectAddin(const Application: IDispatch;
  ConnectMode: ext_ConnectMode; const AddInInst: IDispatch;
  var custom: PSafeArray);
var
  Mon: IMoniker;
  Rot: IRunningObjectTable;
begin
  Mon := nil;
  Rot := nil;
  FApp := Application;
  FAddin := AddInInst;
  if CreateItemMoniker(
       nil,
       PWideChar(GuidtoString(IOutlookGrabber)),
       Mon
       ) <> S_OK then
  begin
    RaiseLastOSError;
  end;

  if GetRunningObjectTable(0, Rot) <> S_OK then
  begin
    RaiseLastOSError;
  end;

  if Rot.Register(
//    ROTFLAGS_ALLOWANYCLIENT, -- Не хорошо!!!
       ROTFLAGS_REGISTRATIONKEEPSALIVE, // Так лучше!!!
       Self as IOutlookGrabber,
       Mon,
       FRotEntry
       ) <> S_OK then
  begin
    RaiseLastOSError;
  end;

end;
//Получение интерфейса "честного" объекта
function TOutlookGrabber.GiveDocumentsToClient: OleVariant;
var
  Rot: IRunningObjectTable;
  Mon: IMoniker;
  TargetObject: IUnknown;
  Grabber: IOutlookGrabber;
  Docs: Documents;
begin
  Result := -1;
  if CreateItemMoniker(nil, PWideChar(GuidToString(IOutlookGrabber)), Mon) <> S_OK then Exit;;
  if not (GetRunningObjectTable(0, Rot) = S_Ok) then Exit;
  if Rot.GetObject(Mon, TargetObject) = S_OK then
  begin
    if TargetObject.QueryInterface(IOutlookGrabber, Grabber) = S_OK then
    with Grabber do
    begin
// this condition defines a running context code
//between the firsts and any other objects
      if Pointer(Grabber) <> Pointer(Self as IOutlookGrabber) then
      begin
//it calls interface the firsts object from any other object
        Result := Grabber.GetData;
      end
      else begin
//        Result := -5;
//this code only performs in the firsts object
        Docs := (FApp as _Application).Documents;
        Result := Docs.Count;
      end;
    end;
  end;
end;



Тестовый код полного сервера и клиента см. в аттаче. Этот код лучше было бы доработать  для фабрики классов, что бы у нас с тобой не плодились объекты (подумай как это сделать, если не додумаешься - подскажу), а был только один глобальный DLL - синглтон.
Кстати на Rsdn было несколько путёвых статей на эту тему. 

Обращаю внимание на вариант: когда у тебя будут запускаться несколько копий оутлука, и соответственно твоих аддинов. Подумай над этим

Поскольку у меня не стоит оутлук, то я накидал работу с word-ом. там тупо возвращается количество созданных документов, я думаю с более сложными структурами ты уже разберёшься.

И ещё, было бы не плохо изменить(дополнить) название темы (Ну что - то типа: Addin DLL singleton, или как - нибудь по другому),
потому как некоторые люди уже спрашивали как делать подобные весчи, совсем не давно. 


Это сообщение отредактировал(а) cat512 - 13.10.2010, 22:57

Присоединённый файл ( Кол-во скачиваний: 5 )
Присоединённый файл  OutlookAddin.rar 338,34 Kb
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: ActiveX/СОМ/CORBA"

Rrader
Girder

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами


  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Delphi
  • Вопросы по SQL и вопросы по базам данных, не связанные с Delphi, задавать здесь

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Rrader, Girder.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: ActiveX/СОМ/CORBA | Следующая тема »


 




[ Время генерации скрипта: 0.0975 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.