Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Конспект лекций РСОИ.doc
Скачиваний:
20
Добавлен:
04.11.2018
Размер:
1.93 Mб
Скачать

2.7.2. Сервер автоматизації

Будь-який застосунок, що має у своєму складі об'єкт автоматизації, який нормально функціонує і зареєстрований в операційній системі відповідним чином, стає сервером автоматизації. Відповідно до канонів COM, можна створювати три типи серверів: внутрішні (in process), зовнішні (out process) і віддалені (remote).

Об'єкт автоматизації інкапсульований у класі TAutoObject, що є нащадком основного класу COM - TCOMObject. Для включення об’єкту автоматизації до складу проекту використовується майстер, що відкривається при виборі значка Automation Object на сторінці Active у бібліотеці стандартних проектів (репозитарії) Delphi.

Примітка1. Реєстрація застосунка в операційній системі як внутрішнього сервера автоматизації виконується командою Register Active Server меню Run. Команда Unregister Active Server застосовується для скасування реєстрації.

Примітка 2. Після реєстрації до сервера може звернутися будь-який застосунок, що має інформацію про методи його інтерфейсу.

2.7.3. Контролер автоматизації

Контролер автоматизації керує роботою сервера, використовуючи методи інтерфейсів сервера автоматизації. Інформація про інтерфейси зазвичай поширюється у вигляді бібліотек типів. Будь-який застосунок, що має доступ до відповідної бібліотеки типів, може стати контролером автоматизації.

Для включення бібліотеки типів до складу проекту можна скористатися командою Import Type Library меню Project. Якщо бібліотека створена в Delphi, можна просто включити ім'я її файла в секцію uses модуля.

У списку діалогу імпорту містяться всі зареєстровані в системі сервери автоматизації. Для кожного з них можна імпортувати бібліотеку типів. Кнопками Add і Remove список можна редагувати.

Після цього в контролері необхідно створити екземпляр класу-оболонки інтерфейсу (CoClass) і застосувати в потрібних місцях потрібні методи сервера автоматизації.

Якщо бібліотека типів недоступна, розробник повинен спочатку на основі змінної типу OleValiant у застосунку-контролері створити об'єкт автоматизації. Для цього використовуються спеціальні функції системної СОМ-бібліотеки CreateOleObject і GetActiveOleObject.

Розглянемо спочатку функцію CreateOleObject, її визначення має вигляд:

function CreateOleObject(const ClassName: string): IDispatch;

var

ClassID: TCLSID;

begin

ClassID := ProgIDToClassID(ClassName);

OleCheck(CoCreateInstance(ClassID, nil, CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, IDispatch, Result));

end;

Функція повертає вказівник на інтерфейс IDispatch. Параметр ClassName визначає ім'я класу автоматизації. Це ідентифікатор програми, що є сервером автоматизації, він відповідає ідентифікатору класу CLSID. Ця функція використовується для внутрішніх і зовнішніх серверів. Сервер, для якого створюється об'єкт має бути зареєстрований.

Функція CreateOleObject спочатку одержує GUID того класу, екземпляр якого необхідно створити. Потім вона передає цей GUID функції CoCreateInstance. Функція ProgIDToClassID являє собою, за суттю, оболонку для виклику функції Windows API CLSIDFromProgID. Отже, функція CreateOleObject працює так само, як функція CreateComObject, за винятком того, що CreateOleObject приймає як параметр ім'я класу, а не GUID.

Однак CreateOleObject завжди створює новий екземпляр сервера, тому якщо бажано підключитися до раніше створеного екземпляра сервера необхідно використовувати функцію GetActiveOleObject.

Функція GetActiveOleObject переглядає таблицю виконуваних об'єктів Windows (Running Object Table), за допомогою якої операційна система веде облік всіх активних у цей момент СОМ-об'єктів, у пошуках потрібного сервера. Якщо такий буде знайдений, то функція GetActiveOleObject поверне посилання на інтерфейс IDispatch цього сервера. Якщо сервер не буде знайдений у таблиці, функція генерує виключення.

Наведений нижче приклад запускає Word, якщо на момент виконання програмного коду він не працює, або підключиться до екземпляру Word, що вже працює, в іншому випадку.

procedure StartOrLinkToWord;

var

V: Variant;

begin

try

V := GetActiveOleObject('Word.Basic');

except

V := CreateOleObject('Word.Basic');

end;

// Далі виконуються будь-які операції з V

end;

Використання змінних типу variant. Змінні типу variant використовуються для керування сервером автоматизації.

При керуванні сервером автоматизації за допомогою змінних типу variant використовується так зване пізнє зв'язування (late binding). Терміном пізнє зв'язування позначається така методика створення програми, при якій усі звернення до методів інтерфейсу не перевіряються на коректність передавання параметрів доти, поки не настане час виконання програми.

Відзначимо, що змінна типу variant не є вказівником на об’єкт. Механізм пізнього зв'язування передбачає, що компілятор Delphi приймає без заперечень усе, що введено в текст програми, і не виконує контролю коректності типів. Іншими словами, Delphi не виконує раннього зв'язування стосовно змінних типу variant.

Розглянемо на прикладі. Наступний програмний код організує підключення до Microsoft Word і містить команди для формування нового файла:

procedure TForm1.Button1Click(Sender: TObject);

var

V: Variant;

begin

V:= Create0leObject('Word.Basic');

V.AppShow; //вікно Word стає видимим

V.FileNew; //створюється новий документ

//команда Insert в документ записує рядок тексту

V.Insert('Автоматизація це просто!');

V.FileSave; //викликає діалог збереження файла

V.DocClose(2); //закриває документ

end;

У цьому прикладі в результаті виклику функції CreateOleObject запускається окремий екземпляр застосунка Microsoft Word. Функція одержує при цьому посилання на інтерфейс Word.Basic і присвоює його змінній V типу variant.

За замовчуванням сервер автоматизації запускається як схований. Після виклику методу V.AppShow застосунок Word виводиться на екран. Потім викликається метод V.FileNew, у результаті чого створюється новий документ Word. Delphi і Windows виконують величезний обсяг роботи, щоб перетворити виклик методу V.FileNew у виклик функції створення нового документа в застосунку Word.

Звернення до методів диспетчерського інтерфейсу відбувається в такий спосіб:

1. Delphi передає ім’я методу сервера методу інтерфейсу IDispatch GetIDsOfNames.

2. Метод IDispatch.GetIDsOfNames повертає числовий ідентифікатор, що однозначно відповідає імені методу сервера.

3. Delphi викликає метод Invoke, використовуючи ідентифікатор, отриманий на кроці 2.

Ця послідовність операцій виконується для будь-якого методу сервера, що викликається через змінну типу variant. Природно, що на їхнє виконання витрачається більше часу, ніж на звернення до того самого об’єкту безпосередньо через інтерфейс.

На використання інтерфейсу IDispatch для звернення до сервера автоматизації є дві досить вагомих причини:

1) іноді програми чи макроси розробляються в середовищі, що не підтримуює бібліотек типів для опису інтерфейсів; прикладами можуть бути Visual Basic чи Microsoft Wor;

2) треба швидко написати працездатну клієнтську програму в Delphi, що не претендує на щось дуже серйозне. Навіщо в такому разі імпортувати бібліотеку типів?

Інтерфейси диспетчеризації. При створенні повноцінних серверів автоматизації, до яких можуть звертатися контролери, що не мають повної інформації про функції сервера, необхідно реалізувати інтерфейси диспетчеризації. Вони є спадкоємцями інтерфейсу IDispatch, але при їхньому оголошенні використовується ключове слово dispinterface.

Кожен елемент інтерфейсу диспетчеризації повинен мати унікальний ідентифікатор DISPID. Властивості повинні мати атрибут "тільки для читання" чи "тільки для запису". Параметри і результати методів, що повертаються, повинні мати тільки такі типи Byte, Currency, Real, Double, Real148, Integer, Single, Smallint, AnsiString, TDateTime,Variant, OleVariant, WordBool.

Для звертання до методів і властивостей інтерфейсів диспетчеризації використовуються методи GetIDsOfNames і Invoke. Інтерфейси диспетчеризації працюють на основі механізму пізнього зв’язування.

Дуальні інтерфейси. У застосунках автоматизації в Delphi використовуються також дуальні інтерфейси, які створюються на базі IDispatch. При оголошенні їх методи обов’язково повинні використовувати директиву safecall. Параметри і результати методів, що повертаються, повинні мати тільки такі типи: Byte, Currency, Real, Double, Real148, Integer, Single, Smallint, AnsiString, ShortString, TdateTime, Variant, OleVariant, WordBool.

Такі інтерфейси підтримують як зв’язування, забезпечене компіляцією застосунка (віртуальна таблиця), так і зв’язування під час виконання (пізнє зв’язування), яке використовується в технології Automation (метод Invoke).

Перші три методи дуального інтерфейсу успадковуються від IUnknown, наступні чотири методи успадковуються від IDispatch, потім йдуть власні методи інтерфейсу.

Контрольні запитання та завдання:

  1. Дайте визначення інтерфейса автоматизації.

  2. Дайте визначення об’єкта автоматизації.

  3. Що таке сервер автоматизації?

  4. Що таке контролер автоматизації?

  5. Опишіть особливості використання функцій CreateOleObject і GetActiveOleObject.

  6. Дайте визначення інтерфейсам диспетчеризації і дуальним інтерфейсам.