Sdílení dokumentů ve stávajícím informačním systému



Podobné dokumenty
Architektura COM. Historie Component Object Model (COM) Komunikace s komponentami Rozhraní komponent COM komponenty v.net.

Diplomová práce Průmyslová automatizace s využitím OPC

Kapitola 1: Co je Delphi 19. Překlad projektu 23

PREPROCESOR POKRAČOVÁNÍ

MATURITNÍ OTÁZKY ELEKTROTECHNIKA - POČÍTAČOVÉ SYSTÉMY 2003/2004 PROGRAMOVÉ VYBAVENÍ POČÍTAČŮ

Teoretické minimum z PJV

Komponenty v.net. Obsah přednášky

Statistica, kdo je kdo?

20. Projekt Domácí mediotéka

Softwarové komponenty a Internet

Mělká a hluboká kopie

Kolekce ArrayList. Deklarace proměnných. Import. Vytvoření prázdné kolekce. napsal Pajclín

Zásuvný modul pro Microsoft Visual Studio. Pavel Plasz

Databázové systémy trocha teorie

Modul ročních zpráv o výsledcích finančních kontrol

Generické programování

Infrastruktura UML. Modelování struktury v UML. Superstruktura UML. Notace objektů. Diagramy objektů

ŠKODA AUTO VYSOKÁ ŠKOLA

Kapitola 1: Co je Microsoft Access? 27 Kapitola 2: Mnoho tváří aplikace Microsoft Access 41 Kapitola 3: Návrh databázové aplikace 75

Věda a výzkum. Univerzitní informační systém. Svazek 4. Slovenská zemědělská univerzita v Nitře

Stručný manuál k ovládání programu STATISTICA. Mgr. Petra Beranová Ing. Miloš Uldrich

Programování v C++ 3, 3. cvičení

5 Rekurze a zásobník. Rekurzivní volání metody

2. přednáška. Databázový přístup k datům (SŘBD) Možnost počítání v dekadické aritmetice - potřeba přesných výpočtů, např.

Parametrizace, harmonogram

Ukázka knihy z internetového knihkupectví

VYUŽITÍ REGIONÁLNÍCH FUNKCÍ A WWW ROZHRANÍ V INTEGROVANÉM KNIHOVNÍM SYSTÉMU KPWINSQL

Metodická příručka pro učitele. InspIS SET modul školní testování

Polymorfismus. Časová náročnost lekce: 3 hodiny Datum ukončení a splnění lekce: 30.března

Component Object Model

Modul EPNO. Téma: Elektronické odesílání evidenčních listů přepravy nebezpečných odpadů

Distanční opora předmětu: Programování v jazyce C Tématický blok č. 8: Dynamické datové struktury, ladění programů Autor: RNDr. Jan Lánský, Ph.D.

2 Základní funkce a operátory V této kapitole se seznámíme s použitím funkce printf, probereme základní operátory a uvedeme nejdůležitější funkce.

Manuál administrátora FMS...2

TÉMATICKÝ OKRUH Softwarové inženýrství

MS ACCESS A MS WORD V KAŽDODENNÍ PRAXI

Více o konstruktorech a destruktorech

Control Section s.r.o.

Component Object Model

DUM 01 téma: Obecné vlastnosti tabulkového editoru, rozsah, zápis do buňky, klávesové zkratky

2 Popis softwaru Administrative Management Center

ZPRACOVÁNÍ NEURČITÝCH ÚDAJŮ V DATABÁZÍCH

SYSTÉM PRO AUTOMATICKÉ OVĚŘOVÁNÍ ZNALOSTÍ

VAR-NET INTEGRAL Manuál správce VNI 5.1 VAR-NET INTEGRAL. verze 0.2. Manuál správce VNI 5.1

InTouch 8.0 Subsystém distribuovaných alarmů

UŽIV ATELSKÁ PŘÍRUČKA

Standardní algoritmy v C++.

Sem vložte zadání Vaší práce.

Základy jazyka C# Obsah přednášky. Architektura.NET Historie Vlastnosti jazyka C# Datové typy Příkazy Prostory jmen Třídy, rozhraní


Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Konfigurace pracovní stanice pro ISOP-Centrum verze

Konstruktory a destruktory

Komponentní technologie

Doplněk Parametry Plus pro Altus Vario

ÚVOD 3 SEZNÁMENÍ SE SYSTÉMEM 4

Abstraktní třídy, polymorfní struktury

QAD CRM. Vladimír Bartoš. konzultant

přetížení operátorů (o)

Jazyk C# (seminář 6)

Individuální projekt z předmětu webových stránek Anketa Jan Livora

Obsah. Úvod Access a Excel podobní, a přesto každý jiný! Vstupujeme do prostředí tabulkového procesoru... 25

UNIVERZITA PALACKÉHO V OLOMOUCI

Helios RED a Internetový obchod

Vytvoření.NET komponenty (DLL) ve Visual Studiu

Databázový systém ACCESS

Sklad v Excelu OBSAH 2/11

Objekty a třídy. Procedurální a objektově orientované programování. V této kapitole se naučíte: Procedurální a objektově orientované programování

Elektronická dokumentace - LATEX. Maticové operace

PRAVIDLA PRO ŽADATELE A PŘÍJEMCE DOTACE Z OPERAČNÍHO PROGRAMU PODNIKÁNÍ A INOVACE PRO KONKURENCESCHOPNOST ZVLÁŠTNÍ ČÁST

Po nastudování této kapitoly byste měli být schopni:

Zpětná vazba od čtenářů 11 Dotazy 11 Zdrojové kódy ke knize 11 Errata 11 Typografické konvence použité v knize 12

8 Třídy, objekty, metody, předávání argumentů metod

elearning tvorba studijních opor

Obrázek 6.14: Prohlížec nápovedy

Střední škola informačních technologií a sociální péče, Brno, Purkyňova 97. Vybrané části Excelu. Ing. Petr Adamec

Dynamicky vázané metody. Pozdní vazba, virtuální metody

Principy objektově orientovaného programování

Úvod do programovacích jazyků (Java)

Elektronická distribuce a správa dokumentů v rámci Policie České Republiky

KAPITOLA 1 SOCIÁLNÍ SÍTĚ A PHP...17

2015 GEOVAP, spol. s r. o. Všechna práva vyhrazena.

Tvorba informačních systémů

Programování II. Návrh programu I 2018/19

Tabulka symbolů. Vazba (binding) Vazba - příklad. Deklarace a definice. Miroslav Beneš Dušan Kolář

Mobilní aplikace Novell Filr Stručný úvod

Nové jazykové brány do Caché. Daniel Kutáč

Projekt Vzdělávání dotykem CZ.1.07/1.3.00/ WORD 2013 práce s textovými soubory. Autoři: Jan Heller a David Peterka

BankKlient. FAQs. verze 9.50

PRAVIDLA PRO ŽADATELE A PŘÍJEMCE DOTACE Z OPERAČNÍHO PROGRAMU PODNIKÁNÍ A INOVACE PRO KONKURENCESCHOPNOST ZVLÁŠTNÍ ČÁST

Delphi podstata, koncepce a metody MDI aplikace

10. Editor databází dotazy a relace

RMI - Distribuované objekty v Javě

Microsoft Office 2003 Souhrnný technický dokument white paper

Ovladač Fiery Driver pro systém Mac OS

ArduinotechGSMShield knihovna

Webové služby a XML. Obsah přednášky. Co jsou to webové služby. Co jsou to webové služby. Webové služby a XML

Vladimír

Dědění, polymorfismus

PB161 Programování v jazyce C++ Přednáška 7

Transkript:

VŠB - Technická univerzita Ostrava Fakulta elektrotechniky a informatiky Katedra aplikované matematiky Sdílení dokumentů ve stávajícím informačním systému 2006

Prohlášení diplomanta Prohlašuji, že jsem celou bakalářskou práci včetně příloh vypracoval samostatně a uvedl jsem všechny použité podklady a literaturu. Chtěl bych poděkovat ing. Petru Foltýnkovi za odbornou pomoc při tvorbě této bakalářské práce. Souhlasím s tím, že s výsledky mé bakalářské práce může být naloženo dle uvážení vedoucího bakalářské práce jako jejího spoluautora a doporučení vedoucího katedry. V případě publikace výsledků nebo její významné části budu uveden jako spoluautor. V Ostravě. podpis diplomanta

Abstrakt Úlohou této práce bylo vyvinout modul popřípadě moduly, které firmě CID International, a.s. lépe pomohou pracovat s dokumenty Microsoft Office, které jsou uloženy v databázi aplikace Market. Ke splnění této úlohy je využita technologie COM, vyvinutá firmou Microsoft. První část práce popisuje potřeby Microsoft Office dokumentů v aplikaci Market a schémata použití těchto dokumentů v aplikaci Market. Druhá část práce shrnuje základní znalosti COM technologie. Od úvodního seznámení přes popis jednotlivých funkcí k popisu důležitých tříd, které se využívají při tvorbě aplikace. Součástí je komentovaný zdrojový kód pro práci s dokumenty typu Microsoft Office. Vyvinuté hotové moduly jsou funkční a jsou vyžívány v produktech firmy CID International, a.s.. Klíčová slova Microsoft Office, COM, dokument,

Seznam zkratek BI CRM COM IDL MDI MSMQ MTS OLE RPC UI vptr WWW Business Inteligence Customer Relationship Management Compoment Object Model Interface Definition Language Multiple dokument interface Microsoft Message Queue Server Microsoft Transaction Server Object Linking and Embedding Remote Procedure Call User interface virtual table pointer World Wide Web

Sdílení dokumentů ve stávajícím informačním systému 6 Obsah Úvod... 7 1 Práce s dokumenty v produktech společnosti CID International, a. s... 8 1.1 Principy použití dokumentu v aplikaci Market... 8 1.1.1 Přístup pomocí kontaktů... 11 1.1.2 Přístup pomocí Požadavku... 14 1.2 Práce s Office dokumenty... 18 2 Technologie COM... 19 2.1 Úvodní seznámení s touto technologií... 19 2.1.1 Základní myšlenka... 19 2.1.2 Úvodní deklarace rozhraní... 20 2.1.3 Skutečné rozhraní COM... 20 2.1.4 Krátké seznámení s jazykem IDL... 21 2.1.5 Rozhraní IUnknown... 21 2.1.6 Vytvoření objektu a jeho používání... 23 2.1.7 Dědičnost a polymorfizmus... 25 2.2 Automation... 26 2.2.1 Rozhraní IDispatch... 27 2.2.2 Návrh rozhraní IDispatch v komponentě... 27 2.2.3 Implementace rozhraní IDispatch... 28 2.2.4 Detekce chyb... 30 3 Základní COM objekty pro práci s Microsoft Office... 32 3.1 Třída COleDispatchDriver... 32 3.1.1 Automation Clients... 32 3.1.2 Automation Server... 33 3.1.3 Členské atributy... 33 3.1.4 Konstruktor... 33 3.1.5 Metody třídy COleDispatchDriver... 34 3.2 Třída _Application... 34 3.3 Třída _Document... 35 3.4 Třída Documents... 35 3.5 Třída COleVariant... 36 3.6 Třída Workbooks... 36 4 Implementace jednotlivých části programu... 38 4.1 Vytvoření Automation Client pro MFC... 38 4.2 Důležitý kód pro MS Word... 38 4.3 Důležitý kód pro MS Excel... 40 4.4 Hotový kód... 42 5 Vyhodnocení výsledků... 43 Použitá literatura... 44

Sdílení dokumentů ve stávajícím informačním systému 7 Úvod Problematika sdílení dokumentů je ve firmě CID International, a.s. velmi naléhavá a důležitá pro její správnou funkčnost a prosperitu. Tuto problematiku řeší zejména aplikace Market. Práce je zaměřena na komunikaci Microsoft Office dokumentů s aplikací Market. Jsou zde popsány způsoby práce s těmito dokumenty v aplikaci Market, je uveden důvod, proč se firma CID rozhodla vyvinout moduly, které slouží k interakci Microsoft Office dokumentů do aplikace Market. Výsledkem této bakalářské práce je popis a realizace interakce Microsoft Office dokumentů s informačním systémem Market. Práce seznamuje s obecnými charakteristikami COM a OLE Automation technologiemi a s objekty vyvinutými firmou Microsoft pro práci s programy Microsoft Office. Poslední část práce se věnuje popisu kódu, který zabezpečuje otevření dokumentu typu Microsoft Word a Microsoft Excel a následně reaguje na uzavření dokumentu uživatelem.

Sdílení dokumentů ve stávajícím informačním systému 8 1 Práce s dokumenty v produktech společnosti CID International, a. s. Společnost CID International, a.s. se je nezávislá společnost (ISV), zabývající se vývojem software pro oblast dopravy, spedice a logistiky zejména v segmentu malých a středních firem. Nosným produktem společnosti je podnikový informační systém pro provozní řízení práce firem v uvedených oblastech podnikání. Podle převažující oblasti činnosti zákazníka je tento informační systém realizován produktem COLLI pro přepravy kusových zásilek, LORI pro firmy s vlastními dopravními prostředky a přepravujícími spíše ucelené zásilky, LOGI pro skladování zásilek a CARGI pro přepravu zásilek po železnici. Pro všechny formy podnikového systému je typická modulární struktura, která umožňuje kombinace všech produktů podle konkrétních provozních potřeb zákazníka. Během doby vývoje systému a jeho provozním používaní se ukázala potřeba doplnit informační systém i moduly, které umožní evidovat a vyhodnocovat obchodní a marketingové aktivity před i po realizaci obchodních případů (segment CRM) a to včetně vazeb na data z provozních systémů. Všechny tyto informace se dále využívají v modulech pro manažerské rozhodování (segment BI). Pro zachovaní celistvosti údajové základny informačního systému bylo k němu přidáno datové a modulární rozšíření soustředěné do nástavby pojmenované Market. Tuto nástavbu firma využívá i pro vlastní potřebu výměny informací a dokumentů jak pro obchodní aktivity, tak pro vnitropodnikové plánování a řízení výroby. V rámci této nástavby je podchyceno vytváření, evidence, oběh a archivování provozních, účetních, rozhodovacích a jiných dokumentů a dokladů včetně vazeb do provozního informačního systému. Práce s dokumenty v elektronickém tvaru je zajišťována programy podle nastavených asociací v prostředí Windows. U dokumentů typu Microsoft Office (.doc,.xls) se jednoduchá vazba přes asociaci v systému, ukázala nedostačující a bylo proto požadováno vyvinout nový modul (případně moduly) pro práci s těmito typy souborů. Modul využívá objektové rozhraní pro těsnější kontrolu nad zpracovávaným dokumentem. Navrhnout a programově realizovat takové rozhraní s vazbou na existující knihovní moduly aplikace Market pro práci s dokumenty je cílem této bakalářské práce. 1.1 Principy použití dokumentu v aplikaci Market Čím dál tím víc informací ukládáme do dokumentů různých typů. Můžeme říct, že v dnešní době máme takto uloženy většinu dat, které potřebujeme a neobejdeme se bez nich. Ne jinak je tomu i ve firmě CID International.a.s.. Důležitá data si zaměstnanci ukládají do dokumentů typu Microsoft Office. Pro lepší přehlednost a bezpečnost se tyto dokumenty ukládají do informačního systému Market. Informační systém Market je postaven na architektuře Klient-Server. Všechny dokumenty (např. *.doc, *.xls), které se používají v informačním systému Market, se ukládají do databáze. Pro uložení dokumentů do databáze Market byly vytvořeny dvě tabulky Dokumenty a VazDokumenty, jejichž schéma je zobrazeno na obr. 1. V tabulce Dokumenty do položky bindata se ukládají dokumenty (např. *.doc, *.xls), které se před uložením do databáze zkomprimují pomocí komprimačního algoritmu. Aktivity, které se provádí při ukládaní a načítání dokumentů z databáze a do databáze jsou zobrazeny na obr. 2. Když je dokument v databázi uložen jako zkomprimovaný, nelze použít fulltextové vyhledávání v dokumentu.

Sdílení dokumentů ve stávajícím informačním systému 9 PK,FK1 Dokumenty liddokumenty PK VazDokumenty lidvazdokumenty FK1 szdokjmeno IDDokFormat szdoktyp bindata ltyp IDUserAdd IDUserMod dtdatumadd dtdatummod szpopis lstav szstav lsmer lpristup IDKategorie rowguid szlocal szcislo dtdatum szznacka szpopisdok szpopiszmeny lverze IDParent lidvazdokumenty Obr. 1. Datový model databáze IDMarketKontakty IDDokumenty IDFirma IDMarkEmail rowguid ID ltyp szlocal Soubor je uložen jako binární zazipovaná data Načte soubor z databáze a odzipuje ho Vložení souboru do systémového adresáře Asociace na otevření dokumentu Obr. 2a) Práce s dokumentem - načítání

Sdílení dokumentů ve stávajícím informačním systému 10 Reakce na uzavření dokumentu Uložení souboru Zazipování souboru Vložení souboru zpět do databaze Obr. 2b) Práce s dokumentem - ukládání Při spuštění aplikace Market se objeví obrazovka, která je základem veškeré práce s Marketem a je zobrazena na obrázku obr. 3. Obr. 3. Okno aplikace Market Pro práci s dokumenty uloženými v databázi Market můžeme použít tyto následující způsoby.

Sdílení dokumentů ve stávajícím informačním systému 11 1.1.1 Přístup pomocí kontaktů V Marketu se můžeme dostat k dokumentům pomocí kontaktů. Obrazovka kontaktů je ukázaná na obrázku obr. 4. Okno dokumentů Obr. 4. Okno Kontaktů Pro vyvolání okna Kontaktů viz. obr.4 se použijí knihovny, které jsou zobrazeny v komponentovém diagramu Kontaktů viz. obr. 5. «volá» «spustitelný soubor» Market «komunikace s DB» SQL server na kterém běží databáze market «komunikace s DB» «knihovna» _amkkontakty ADO «DB Server» Databáze Market «volá» «knihovna» _amkdokutyp «komunikace s DB» «volá» «knihovna» _amkdokuword Obr. 5. Komponentový model Kontaktů

Sdílení dokumentů ve stávajícím informačním systému 12 Popis událostí, vyskytující se při načítání a ukládání dokumentu, je zobrazen na sekvenčním diagramu a diagramu stavů. Sekvenční diagram je zobrazen na obr. 6. a diagram stavů je zobrazen na obr. 7. Market MS Office Market _amkkontakty _amkdokutyp _amkdokuword Instance Wordu volání knihovny() volání knihovny() volání knihovny() CreateDispatch() IsUkoncenWord() Zda se mají uložit změny Uložit změny Uvolnění knihovny Uvolnění knihovny Probíha dokud není word uzavřen. Jakmile je uzavřen, ptáme se na změny. příjímá zprávu, zda se mají změny uložit Obr. 6. Sekvenční diagram pro kontakty

Sdílení dokumentů ve stávajícím informačním systému 13 Market Kontakty Dokument Word Volání knihovny _amkkontakty Volání knihovny _amkdokutyp Načtení dat z DB Uloženi souboru do temp adresáře Volání knihovny _amkdokuword Otevření dokumentu Překreslení obrazovky Testování, zda je dokument ještě otevřen Je již uzavřen Uložení dat do DB Ukládání změn Zda se mají uložit změny Uvolnění souboru z temp adresáře Uvolnění Dll z paměti Uvolnění Dll z paměti Obr. 7. Diagram stavů pro kontakty

Sdílení dokumentů ve stávajícím informačním systému 14 1.1.2 Přístup pomocí Požadavku Druhým způsobem přístupu k dokumentů uložených v databázi je pomocí požadavku. Na obrázku obr. 8. je zobrazena obrazovka pro přístup k dokumentu pomocí požadavku. Obr. 8 Obrazovka Marketu s požadavkem Pro vyvolání okna Požadavku viz. obr. 8 se použijí knihovny, které jsou zobrazeny v komponentovém diagramu Požadavků viz. obr. 9. «volá» «spustitelný soubor» Market «komunikace s DB» SQL server na kterém běží databáze market «komunikace s DB» «knihovna» _amkpozadavek ADO «DB Server» Databáze Market «volá» «knihovna» _aedokument «komunikace s DB» «volá» «knihovna» _amkdokuword Obr. 9. Komponentový model Požadavku

Sdílení dokumentů ve stávajícím informačním systému 15 Popis událostí, vyskytující se při načítání a ukládání dokumentu, je zobrazen na sekvenčním diagramu a diagramu stavů. Sekvenční diagram je zobrazen na obr. 10. a diagram stavů je zobrazen na obr. 11. M arket M S O ffice M arket _amkpozadavky _aedokum ent _amkdokuw ord Instance W ordu volání knihovny() volání knihovny() volání knihovny () CreateD ispatch() IsUkončenW ord Zda se m ají uložit změny Uložit zm ěny Uložit změny Uvolnění knihovny Probíhá dokud není word uzavřen. Jakm ile je uzavřen, ptám e se na změny. příjím á zprávu, zda se m ají změny uložit Obr. 10. Sekvenční diagram požadavku

Sdílení dokumentů ve stávajícím informačním systému 16 Market Požadavky Dokument Word Volání knihovny _amkpožadavky Volání knihovny _aedokument Načtení dat z DB Uloženi souboru do temp adresáře Volání knihovny _amkdokuword Otevření dokumentu Překreslení obrazovky Testování, zda je Dokument ještě otevřen Je již uzavřen Uložení dat do DB Ukládání změn Zda se mají uložit změny Uvolnění souboru z temp adresáře Uvolnění Dll z paměti Uvolnění Dll z paměti Obr. 11. Diagram stavů pro požadavek Většina dokumentů, ať se již jedná o soubor typu Word nebo Excel, vzniká na základě požadavku. Vznik dokumentu na základě požadavku je ukázán na obrázku obr. 12.

Sdílení dokumentů ve stávajícím informačním systému 17 Na začatku stojí požadavek Vytvoří se dokument Probíhá analýza Připomínky k analýze Schválení analýzy Předání prográmatorovi Konzultace analyzy s analytikem Jsou připominky Nejsou připomínky Programovaní požadavku V průběhu programování se vyskytly další připomínky Nejsou připomínky Vytvoření modulu Nové požadavky k modulu Zákazník si požádal o úpravy modulu Obr. 12 Diagram vzniku dokumentu

Sdílení dokumentů ve stávajícím informačním systému 18 1.2 Práce s Office dokumenty Firma CID měla vytvořen modul pro otevírání dokumentu a reakci na jeho uzavření. Tento modul pracoval na principu vyvolávání procesů a následně čekal na ukončení tohoto procesu. Tento modul byl funkční pouze pro situaci: otevření jednoho dokumentu. Jakmile uživatel otevřel více Office dokumentů, dokumenty se otevřely v jednom okně a modul nebyl schopen rozpoznat uzavření jednotlivých Office dokumentů. Aplikace Microsoft Office (např. Word) pracují na základech MDI okna. To znamená jedna aplikace otevře více oken, v kterých je otevřeno více dokumentů. Původní modul neměl přístup k instancím jednotlivých dokumentů, a proto nemohl rozpoznat uzavření jednotlivých dokumentů otevřených v MDI okně. Vyvstal tedy požadavek vyvinout modul, který každý nově otevřený dokument otevře v novém okně a dokáže rozpoznat uzavření jednotlivých Office dokumentů uživatelem. Po složitém hledání možností, jak vyřešit tento problém, se firma rozhodla řešit tento problém s pomocí COM technologie.

Sdílení dokumentů ve stávajícím informačním systému 19 2 Technologie COM 2.1 Úvodní seznámení s touto technologií Technologie COM je dílem světoznámé firmy Microsoft. Má za sebou dlouhou dobu vývoje. Její začátky se datují v technologii OLE, která dokázala inteligentně vkládat dokumenty jednotlivých aplikací do jiných aplikací. To bylo sice možné již dříve, ale pomocí OLE jsme mohli kromě dat vkládaných do dokumentů uchovávat i informace o jeho zdroji. Tato technologie se samostatně objevila poprvé až v roce 1995. Od té doby sledujeme její mohutný rozvoj a uplatnění. Ukázalo se, že za její pomoci se rozsáhlé projekty stávají jednoduššími a snáze se dají řešit mnohé problémy. Tímto ale rozvoj komponentové tvorby softwaru neskončil. Objevila se snaha jednotlivé komponenty distribuovat pomoci počítačových sítí. Toto již bylo na jiných platformách vyřešeno. Proto se firma Microsoft rozhodla implementovat RPC, neboli Vzdálené volání procedury do svých systémů. RPC bylo použito pro základní volání vzdálených funkcí distribuovaných komponent. Diky tomu v roce 1996 vznikla distribuovaná verze COM nazvaná jako DCOM. Komponenty COM a DCOM jsou převážně používány ve velkých systémech, kde velká část kódu je věnovaná otázce spolehlivosti, ověřování bezpečnosti a řízení selektivního přístupu. Velmi často se současně řeší obsluha několika klientů a z toho vyplývají problémy synchronizace a přístupu ke sdíleným datovým zdrojům. Na základě COM, DCOM, MTS (řeší problémy současné obsluhy více klientů, řízení bezpečnosti, ošetřování chybových stavů) a MSMQ (umožňuje zapisovat požadavky na straně klienta do fronty a přenášet na server) vznikla technologie COM+. COM+ není pouhou integrací těchto technologií,ale současně tyto technologie vylepšuje. 2.1.1 Základní myšlenka Komponentová technologie je postavena na binárně nezávislém komunikačním nástroji nazvaném Rozhraní neboli Interface. Rozhraní nám představuje datový typ, v němž deklarujeme seznam funkcí, které bude klient smět využívat. Je třeba zdůraznit, že rozhraní je pouze seznamem funkcí, není zde jejich definice a rozhraní neobsahuje ani žádná členská data, která by způsobila nekompatibilitu. Využíváme také datovou strukturu Třída, která realizuje vlastní komponentu. Tato třída implementuje již dříve definované rozhraní. Třída také implementuje svá členská data a vlastní funkce, pokud je potřebuje, a hlavně obsahuje implementaci všech funkcí, které jsou definovány v rozhraní. Obecně můžeme říci, že rozhraní stanovuje způsob komunikace, mezi libovolnou komponentou a klientem. Konkrétní komponenta dává jednotlivým funkcím rozhraní určitou podobu. Základem je pravidlo, kterým stanovujeme, že klientské aplikaci poskytujeme pouze informace o rozhraní a ne o konkrétní implementaci. Klient tedy nemá možnost zjistit jak vypadá implementace a je schopen vyvolávat pouze funkce rozhraní, které jsme mu poskytli. Tímto popsaným postupem se vyřešily mnohé problémy, které se vyskytovaly v minulosti.

Sdílení dokumentů ve stávajícím informačním systému 20 2.1.2 Úvodní deklarace rozhraní Rozhraní se v každém programovacím jazyce tvoří různě. Společné pro všechny jazyky je výsledný produkt binárně kompatibilní rozhraní. Binární kompatibilitou rozumíme fakt, že vytvořené komponenty mohou být po svém přeložení používány jakýmikoliv klienty nezávisle na jazyce, v kterém byli napsány. V programovacím jazyce C++ říkáme, že rozhraní je abstraktní třída, která obsahuje pouze čisté virtuální funkce. Třídám, které nemají žádná členská data a ani žádnou implementaci deklarovaných funkcí, říkáme Čistá abstraktní třída, Protokolová třída, nebo jednoduše Interface. Na ukázku si vytvoříme jedno rozhraní IAuto a třídu komponenty Auto implementující vytvořené rozhraní. class IAuto { public: virtual int pocetkol() const = 0; ; class Auto : public IAuto { int m_pock; public: int pocetkol() const { return m_pock; ; Každá třída obsahující virtuální funkce, má definovanou tabulku virtuálních funkcí. Existuje vždy pouze jedna pro daný typ třídy a je sdílena všemi instancemi třídy. Každá instance třídy obsahuje ukazatel na tabulku a ten často označujeme zkratkou vptr. Tabulka obsahuje ukazatele na implementace všech virtuálních funkcí v dané třídě. 2.1.3 Skutečné rozhraní COM U komponenty musíme zařídit, aby si sama řídila svoji životnost na základě počtu připojených klientů. Pro tento účel bylo v technologii COM vytvořeno rozhraní IUnknown. Díky jeho dvou funkcí AddRef a Release můžeme velmi jednoduše řídit životní cyklus instance komponenty. Třetí funkcí rozhraní IUnknown je QueryInterface, která nám dává ukazatel na rozhraní v případě, že komponenta implementuje více rozhraní. Skutečná deklarace rozhraní IAuto bude vypadat takto: class IAuto : public IUnknown { public virtual HRESULT stdcall pocetkol(int *vysledek) = 0; ; Rozhraní IAuto nazýváme Uživatelské rozhraní, protože výčet metod je pouze na programátorovi. Vedle uživatelských rozhraní máme v COM, DCOM i v COM+ mnoho připravených rozhraní, jako je třeba IUnknown. Většina uživatelských rozhraní je přímo či nepřímo odvozena od IUnknown. Když porovnáme původní návrh rozhraní IAuto se skutečným, vidíme že funkce pocetkol doznala malých změn. Prvním rozdílem je návratová hodnota HRESULT. Tato hodnota je 32 bitové číslo, které definuje, zda funkce uspěla či selhala. Používá se u většiny funkcí rozhraní.

Sdílení dokumentů ve stávajícím informačním systému 21 Druhým rozdílem je použití volací konvence, kterou určujeme klíčovým slovem stdcall. Volací konvence nám určuje, jak budou funkci (pocetkol) předávány parametry a kdo bude parametry ze zásobníku odstraňovat. V jazyce C a C++ musíme vždy použít klíčové slovo stdcall, protože implicitní volací konvence je cdecl, která ovšem není kompatibilní s ostatními programovacími jazyky. Tím bychom porušili binární kompatibilitu rozhraní a nemohla by být použita široká množina jazykově odlišných klientů, o kterou se snažíme. 2.1.4 Krátké seznámení s jazykem IDL Jazyk IDL byl používán pro popis datových typů a funkcí, jež byli spouštěny mimo počítač klienta. Poté ho firma Microsoft nejenom přejala, ale i rozšířila jeho schopnosti o možnosti popisu objektových rozhraní COM komponent. Jazyk IDL se používá pouze pro popis konstant, datových struktur, funkcí a rozhraní, které budou použity pro tvorbu COM komponent. Popis rozhraní v IDL jazyce je tedy jen pojítkem mezi aplikací klienta a aplikací komponenty. Pro malou ukázku si ukážeme, jak bychom napsali naše rozhraní IAuto v IDL jazyce: import unknnw.idl ; [object, uuid (123445678-1234-0000-abcd-00000000001)] interface IAuto:IUnknown { HRESULT pocetkol([out, retval] int *pcvysledek); Vidíme, že definice rozhraní se skládá: a) z atributů rozhraní uvedených v hranatých závorkách, kde definice vždy začíná klíčovým slovem object; poté následuje další klíčové slovo uuid, pomocí něj je každému rozhraní přiděleno jedinečné 128 bitové číslo, které je zapsáno pomocí hexadecimální konstanty uvedené v kulatých závorkách. Toto číslo je označované zkratkou GUID. b) z klíčového slova interface, názvu rozhraní, dvojtečky a jména rodičovského rozhraní, které je v našem případě IUnknown. Jelikož rozhraní IUnknown existuje, je třeba na začátek IDL souboru vložit jeho definici tedy příkaz import unknnw.idl c) ze složených závorek které obsahují deklarace funkcí rozhraní, doplněnými mnohými atributy, uvedených v hranatých závorkách. Úplný výčet všech atributů můžeme najít v oficiální dokumentaci firmy Microsoft. 2.1.5 Rozhraní IUnknown IUnknown je rozhraní, které musí každá COM komponenta bezpodmínečně implementovat, nezávisle na tom kolik dalších rozhraní daná komponenta implementuje. IUnknown je rozhraní, na které se může každý klient spolehnout. Je základním rozhraním pro tvorbu většiny dalších rozhraní každého COM objektu. Toto rozhraní obsahuje sice jenom tři metody, ale přítomnost rozhraní je pro každý objekt životně důležitá a nepostradatelná. Jak jsme si už ukázali, životnost objektu sledujeme na základě počtu referencí. Tedy základní princip spočívá v myšlence u každé instance objektu počítat kolik má klientů, nebo kolikrát se

Sdílení dokumentů ve stávajícím informačním systému 22 tentýž objekt odkazuje na danou instanci. To znamená, že klient neprovádí zrušení objektu v paměti počítače, nýbrž mu pouze oznámí, že instanci nehodlá dále používat. Poté co to provedou všichni klienti, objekt u poslední instance zjistí, že není dále potřebný a sám provede svou destrukci. K tomu, aby toho byl klient schopen obsahuje, rozhraní IUnknown funkce AddRef a Release. Všechny objekty musí ještě obsahovat celočíselné počítadlo, které bude obsahovat počet aktuálních odkazů všech připojených klientů. Funkce AddRef inkrementuje počítadlo referencí všech připojených klientů a vrací aktuální počet klientů. Funkce Release dekrementuje počítadlo referencí. Pokud počítadlo dosáhne hodnoty nula, objekt se sám odstraní z paměti. Tato funkce opět vrací aktuální stav počítadla referencí. Poslední funkcí rozhraní IUnknown, jak jsme se už zmínili, je QueryInterface. Tato funkce slouží k dotazu na existující rozhraní, které je identifikováno prvním parametrem. Pokud objekt toto rozhraní implementuje, vrátí na něj odkaz ve druhém parametru. Pokud ovšem objekt neimplementuje toto rozhraní, návratová hodnota funkce má hodnotu E_NOINTERFACE a druhý parametr má neplatnou hodnotu. Tato funkce dává klientovi možnost získat novou referenci, ale také zjistit, zda komponenta zvolené rozhraní podporuje. Po popsání funkce jednotlivých funkcí rozhraní IUnknown je třeba si uvědomit dvě věci. První, že po vytvoření nového odkazu na libovolné rozhraní je třeba bezprostředně volat funkci AddRef. A druhá, že pokud chceme aby odkaz na rozhraní zaniknul, musí se před jeho zánikem volat funkce Release. Teď si ukážeme jak by měli jednotlivé funkce rozhraní vypadat na třídě Auto. class Auto : public IAuto { public: //Funkce rozhraní IUnknown ULONG stdcall AddRef(); ULONG stdcall Release(); HRESULT stdcall QueryInterface(REFIID riid, void** ppv); //Funkce rozhraní IAuto HRESULT stdcall pocetkol(int *vysledek); private: ULONG m_cref; ; //funkce AddRef která zvyšuje počítadlo referencí ULONG Auto :: AddRef() { return ++m_cref; //funkce Release, která snižuje počítadlo referencí a pokud //proměnná m_cref je rovna nule odstraní objekt z paměti ULONG Auto :: Release() { if(--m_cref!= 0) //test jestli to není poslední reference return m_cref; else { delete this; return 0; //je to poslední reference, samodestrukce

Sdílení dokumentů ve stávajícím informačním systému 23 //Funkce QueryInterface, která na základě IID rozhraní přiřazuje //ukazateli ppv korektně přetypovaný ukazatel this HRESULT Auto :: QueryInterface(REFIID riid, void** ppv) { if(riid == IID_IUnknown) { //implementuje jen IUnknown *ppv = (IUnknown*)this; else if(riid == IID_IAuto) { //implementuje IAuto *ppv = (IAuto*)this; else { *ppv = NULL; return E_NOINTERFACE; //konstanta signalizující //neexistující rozhraní //Funkce z rozhraní IAuto, pouze pro ilustraci HRESULT Auto :: pocetkol(int *vysledek) { *vysledek = 4; //na ukazku uložíme hodnotu čtyři return S_OK; //konstanta signalizující vše je OK Máme tedy představu jak může deklarace komponenty vypadat. 2.1.6 Vytvoření objektu a jeho používání Prvním krokem je inicializace COM knihovny a to provedeme voláním jedné ze dvou funkcí. První funkce HRESULT CoInitializeEx( void pvres, DWORD dwcoinit) inicializuje COM knihovnu, abychom byli potom schopni využít její služeb. První parametr je rezervován pro budoucí použití, ale teď ho musíme vždy nastavit na hodnotu NULL. A druhý parametr nastavíme na jednu z konstant, buď COINIT_APARTMENTTHREADED, nebo COINIT_MULTITHREADED, které určují použitý threadový model. Druhá funkce HRESULT CoInitialize ( void * ) je jednoduší varianta funkce CoInitializeEx a její použití je ekvivalentní s voláním CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); Tak jak musíme na začátku každého programu volat funkci CoInitialize nebo CoInitializeEx, musíme na jeho konci volat funkci CoUninitialize. Její použití je jednoduché, protože tato funkce nemá žádné parametry. Jejím úkolem je provést určitý úklid po používané COM knihovně, jako je například uvolnění systémových, zdrojů nebo ukončení všech RPC spojení. Jedna z možností, jak vytvořit objekt, je použít funkci CoCreateInstance. Je to jedna z nejjednodušších a nejpoužívanějších funkcí. Její deklaraci máme tady: HRESULT CoCreateInstance( REFCLSID rclsid, LPUNKNOWN punkouter, DWORD dwclscontext, REFIID riid, LPVOID *ppv); Význam parametru je uveden v tabulce Tab.1. Parametr Význam rclsid Identifikátor COM třídy, jejíž instanci chceme vytvořit. Často označovaný zkratkou CLSID. CLSID je GUID. punkouter Ukazatel na rozhraní IUnknown. Pokud má ukazatel hodnotu NULL, zakládáme instanci běžným způsobem. Pokud to není NULL provádíme

Sdílení dokumentů ve stávajícím informačním systému 24 takzvanou agregaci objektu. dwclscontext Hodnota definuje tzv. kontext, v jakém bude spuštěna. Určuje tedy, zda bude komponenta spouštěna jako součást klientského, nebo svého vlastního procesu. Také určuje, jestli půjde o lokální nebo vzdálenou komponentu. riid GUID rozhraní, které chceme získat po vytvoření instance komponenty. ppv Výstupní parametr funkce obsahující ukazatel na rozhraní požadované předchozím parametrem. Tab.1: Význam parametrů funkce COCreateInstance Podívejme se na jednotlivé parametry trochu podrobněji. Při vytváření instance komponenty potřebujeme dvě GUID čísla. Jedno pro rozhraní a druhé pro samotný objekt, jehož instanci chceme vytvořit. Problém s pojmenováním objektu je stejný jako u rozhraní. Jméno Auto je sice pěkně čitelné, ale nemusí být jedinečné. Proto používáme GUID i pro označení objektu, kterému se říká CLSID z angličtiny Class Identifier. První parametr je právě CLSID. COM využívá informace zapsané v Registrech k zavedení komponenty do paměti počítače a vytvoření instance objektu. Pro určení binárního souboru, který komponentu obsahuje, je třeba použít klíč HKEY_CASSES_ROOT\CLSID\, ve kterém jsou uvedena všechna CLSID komponent nainstalovaných v operačním systému. Pod každým klíčem je ukryto mnoho informací o konkrétním objektu. Nejdůležitější informací je jméno DLL knihovny, nebo EXE souboru, ve kterém se nachází kód komponenty. Druhý parametr určuje, zda je základní objekt vytvořen samostatně; pak má hodnotu NULL, nebo je interní součástí jiného objektu, který ho agreguje. Třetí parametr je podstatně složitější. Jeho hodnota určuje, jak bude komponenta zavedena do paměti. Komponenta musí být pro zvolený postup správně vytvořena. Jednotlivé možnosti si ukážeme v tabulce Tab. 2, kde v prvním sloupci je uvedena konstanta, kterou můžeme použít místo třetího parametru. Druhý sloupec zobrazuje odpovídací klíč z Windows Registry. Poslední sloupec je vysvětlení jednotlivé volby. Konstanta Klíč Registry Popis CLSCTX_INPROC_SERVER InproceServer32 Komponenta bude zavedena do adresního prostoru klientské aplikace. V klíči Registry je uvedena plná cesta k DLL knihovně CLSCTX_LOCAL_SERVER LocalServer32 Komponenta bude zavedena do svého vlastního paměťového prostoru v nově vytvořeném procesu. V Registry je uložená plná cesta k EXE programu. CLSCTX_REMOTE_SERVER AppID Komponenta bude zavedena do svého vlastního paměťového prostoru, ale v procesu na jiném počítači. CLSCTX_INPROC_HANDLER InprocHandler32 Jde o speciální konstantu pouze pro COM+ komponenty. Tab.2: Konstanty pro druhý parametr funkce CoCreateInstance Poslední dva parametry jsou spjaty s požadovaným rozhraním, které chceme získat, abychom mohli s objektem pracovat. V našem případě můžeme přímo požádat o rozhraní IAuto, ale často se doporučuje požádat o rozhraní IUnknown. Pokud bychom si ovšem nebyli jisti, jaké rozhraní objekt implementuje, jistotou v každém případě je rozhraní IUnknown. Tímto dostaneme

Sdílení dokumentů ve stávajícím informačním systému 25 komponentu do paměti a poté můžeme opakovaně používat metodu QueryInterface, abychom zjistili, jaké rozraní komponenta implementuje. Čtvrtým parametrem je IID požadovaného rozhraní a pátý parametr je ukazatel na toto rozhraní, samozřejmě pokud existuje. Úspěšnost zavedené komponenty a existence rozhraní signalizuje návratová hodnota typu HRESULT. Teď si pro malou ukázku ukážeme jak by tento kód mohl vypadat. #define _WIN32_DCOM #include <iostream.h> #include komponenta\auto.h //Generováno překladačem const CLSID CLSID_Auto = {0x12345678, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02; void main() { IUnknown* punknown; IAuto* pauto; HRESULT hr = CoInitialezeEx(NULL, COINIT_APARTMENTTHREADED); if(failed(hr) cout << Nelze inicializovat << endl; hr = CoCreateInstance(CLSID_Auto, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**) &punknown); if(failed(hr) cout << Nelze zalozit instanci komponenty. << endl; hr = punknown->queryinterface(iid_iauto, (void**) &pauto); if(failed(hr)) cout << Komponenta nepodporuje rozhrani IAuto. ; punknown->release(); int cislo = 0; hr = pauto->pocetkol(&cislo); if(succeeded(hr)) cout << Pocet kol osobniho auto je: << cislo << endl; pauto->release(); CoUnitilializace(); Podle mého názoru je tato ukázka dostatečně názorná a je na ni vidět základní použití jednotlivých funkcí, které jsme si popisovali v předchozích odstavcích. 2.1.7 Dědičnost a polymorfizmus V technologii COM mluvíme o tzv. implementační dědičnosti. Implementační dědičnost má vedle výhod, jako jsou opakované využití kódu a základ pro realizaci polymorfizmu, i závažné nevýhody. První nevýhodou je striktní závislost na použitém programovacím jazyce. Druhou nevýhodou je problematické chování metod základní třídy. Z toho vyplývá, že implementační dědičnost není v COM technologiích vhodná, protože nepodporuje jazykovou nezávislost a vytváří potenciálně nestabilní kód.

Sdílení dokumentů ve stávajícím informačním systému 26 S dědičností v objektově orientovaném programování jde ruku v ruce polymorfizmus. Polymorfizmus v COM chápeme trochu jinak, než v objektově orientovaných jazycích. Rozdíl je v jeho implementaci. V C++ a dalších jazycích se polymorfizmus realizuje pomocí dědičnosti tříd, ale u COM komponent se tato vlastnost realizuje implementací společné množiny rozhraní. V COM technologii se doporučuje, aby rozhraní nedědila navzájem od sebe, ale aby dědila od základního rozhraní IUnknown. Tím dostaneme více nezávislých rozhraní pro implementaci různých komponent. Tímto způsobem se vyhneme mnoha nepříjemnostem a ušetříme spoustu času. V této kapitole si ještě popíšeme, jak z existujících komponent vytvořit komponenty nové. K tomu máme dvě techniky umožňující využívaní existujících komponent pro tvorbu nových. Tyto techniky se v angličtině jmenují Containment a Aggregation. Containment je jednodušší z představovaných technik. Využívá existujících komponent a pro svou jednoduchost je často využívaná. Vnější komponenta vytvoří interně instanci vnitřní komponenty klasickým způsobem a začne využívat jejich služeb. Aby to ovšem fungovalo, musí vnější komponenta kromě svých rozhraní ještě implementovat všechna rozhraní vnitřní komponenty. Agregace je druhou metodou, která využívá existujících komponent jako součásti jiné komponenty. U agregace opět vnější objekt využívá vnitřní objekt, avšak nevystupuje jako prostředník pro volání metod rozhraní vnitřní komponenty. Vnitřní komponentě je tedy umožněno přímo vystavit svá rozhraní navenek. Agregace má své výhody, ale i své nevýhody. Jedna z výhod je urychlené volání metod vnitřního rozhraní. Velkou nevýhodou je její obtížná implementace, kde je velký problém v tom, že vnitřní komponenta absolutně nic neví o komponentě vnější. 2.2 Automation Komunikace mezi klientskou aplikací a komponentou je založena na schopnosti porozumět na obou stranách binárnímu rozhraní. To znamená, že obě komunikující strany musí využívat tabulky virtuálních funkcí. Toto jsme si popisovali až doposud. V COM technologii však existuje ještě další metoda komunikace, označovaná jako Automation, dříve jako OLE Automation, které využívá univerzální rozhraní IDispatch. Uvedenou techniku komunikace často využívají aplikace jako jsou programy rodiny Microsoft Office nebo skriptovací jazyky. Rozhraní mohou být sestavena z nekonečné množiny různých funkcí s různými parametry. Komponenty proto nabízely vedle těchto rozhraní i rozhraní IDispatch. Jeho IID i množina funkcí je napevno daná, jako to je u rozhraní IUnknown. Druhým důvodem zavedení Automation je důležitá podpora COM technologie pro skriptovací jazyky. V posledních letech vzrostla popularita skriptovacích technologiích realizovaných pomocí internetových jazyků. Většinu skriptů můžeme napsat i jako součást HTML nebo ASP stránek. Nemalou množinu aplikací tvoří programy napsané ve Visual Basic for Application, které se mohou stát součástí dokumentů popřípadě sešitů v Microsoft Wordu nebo Excelu. Technika Automation není úplně odlišná od principů COM. Její princip je postaven na základních kamenech položených technologií COM. Komponentě COM implementující rozhraní IDispatch se také říká Automation server, který poskytuje klientům různé služby. Na rozdíl od uživatelsky definovaných rozhraní nejsou funkce serveru volány přímo, ale přes mechanizmus zabudovaný přímo ve funkcích rozhraní IDispatch.

Sdílení dokumentů ve stávajícím informačním systému 27 2.2.1 Rozhraní IDispatch Je to jediné rozhraní, které musí komponenta implementovat, samozřejmě vedle IUnknown, aby mohla poskytnout veškerou funkcionalitu Automation. Toto rozhraní definuje pouze čtyři funkce ( GetTypeInfoCount, GetTypeInfo, GetIDsOfNames a Invoke). Základní myšlenka chovaní tohoto rozhraní spočívá ve funkci zprostředkovatele volání mezi komponentou a klientem. Rozhraní samotné neobsahuje žádné specifické funkce, které hodlá klient volat. Skutečné funkce jsou na straně komponenty očíslovány pomocí jedinečných čísel, které nazýváme DISPID Dispatch identifier. Nejdůležitějšími funkcemi rozhraní jsou GetIDsOfNames a Invoke. Klientská aplikace zná jedině jméno volané funkce a toto jméno dá funkci GetIDsOfNames jako její parametr. Funkce vyhledá v tabulce, která je uložená v komponentě, DISPID odpovídající zadanému jménu funkce a vrátí ji klientovi. Klient se tedy dozvěděl jakou funkci bude ve skutečnosti volat. S hledaným DISPID a množinou parametrů následovně vyvolá funkci Invoke. Ta na základě DISPID spustí konkrétní implementaci požadované funkce. Funkce Invoke používá indexovou tabulku ukazatelů na jednotlivé funkce. Aby ke komponentě mohli přistupovat všechny typy klientů, je nutné, aby komponenta implementovala rozhraní IDispatch. Existuje ale ještě další implementace Automation rozhraní, nazvané jako Duální rozhraní (Dual Interface). Komponenta, která implementuje duální rozhraní, umožňuje klientům využívat IDispatch stejně jako uživatelsky definované rozhraní. Realizace techniky Automation za pomoci duálního rozhraní je mnohem obvyklejší než předchozí metoda pracující s čistým rozhraním IDispatch. Duální rozhraní umožňuje přirozený přístup k funkcím komponenty. Nepochybnou výhodou duálního rozhraní je i možnost volat funkce rychlejším způsobem. 2.2.2 Návrh rozhraní IDispatch v komponentě Použití rozhraní IDispatch v komponentně musíme předem promyslet, pokud budeme implementovat čisté nebo duální rozhraní. Naše rozhodnutí ovlivní způsob, jak budeme definovat rozhraní v IDL souboru. Volba hlavně závisí na množině klientů, kteří budou komponentu využívat. Jeli komponenta určena pouze pro skriptovací jazyky, je použití duálního rozhraní zbytečné, ale pokud je jen malá šance využít komponentu v C++, je lepší využít duální rozhraní. Pokud se rozhodneme implementovat čisté rozhraní IDispatch v IDL souboru, použijeme na jeho definici klíčové slovo dispinterface. Tímto slovem se rozhraní často označuje. [uuid(12345678-0000-0000-0000-000000000001)] dispinterface IAuto { [id(1), propget] HRESULT pocetkol([out, retval] int *pcvysledek); Při definici rozhraní dispinterface musíme dodržet několik základních pravidel, které jsou: 1. V atributech rozhraní nemusíme uvádět klíčové slovo object. 2. Rozhraní ve své definici není odvozeno od IUnknown, ale klíčové slovo dispinterface zajistí potřebnou dědičnost. 3. Každá funkce je očíslovaná atributem id. Číslovaní musí být v rámci rozhraní jedinečné. Přiřazené číslo nazýváme DISPID.

Sdílení dokumentů ve stávajícím informačním systému 28 4. Rozhraní může definovat tak zvané properties neboli vlastnosti. 5. Deklarované funkce mohou obsahovat jenom Automation. Poněkud jinak bude vypadat definice duálního rozhraní, které v mnohém připomíná uživatelské rozhraní. Definice opět začíná přiřazením atributů jako je například uuid a přidáme klíčové slovo dual, které je pro duální rozhraní zásadní. Důležitá je také dědičnost ze základního rozhraní IDispatch. Tím pádem vzniká tabulka virtuálních funkcí, která obsahuje funkce rozhraní IUnknown, IDispatch a dalších rozhraní, které přidáme. [object, uuid (123445678-1234-0000-abcd-00000000001), dual ] interface IAuto : IDispatch { [id(1), propget] HRESULT pocetkol([out, retval] int *pcvysledek); 2.2.3 Implementace rozhraní IDispatch Způsob implementace se může značně lišit. Jak jsme si řekli, programátor v C++ musí napsat implementaci všech funkcí sám. Může si ale zvolit způsoby realizace funkcí rozhraní IDispatch od nejjednodušších až po velmi složité. Je tedy nutné zvážit známý poměr cena / výkon. Ted si ukážeme, jak by vypadala naše třída Auto v Automation. class Auto : public IAuto { public: //Funkce rozhraní IUnknown ULONG stdcall AddRef(); ULONG stdcall Release(); HRESULT stdcall QueryInterface(REFIID riid, void** ppv); //funkce rozhraní IDispatch HRESULT stdcall GetTypeInfoCount(UINT* pcounttypeinfo); HRESULT stdcall GetTypeInfo(UINT itypeinfo, LCID lcid, ITypeInfo** ppitypeinfo); HRESULT stdcall GetIDsOfNames(REFIID riid, LPOLESTR* rgsznames, UINT cnames, LCID lcid, DISPID* rhdispid); HRESULT stdcall Invoke(DISPID dispidmember, RERIID riid, LCID lcid, WORD wflags, DISPPARAMS* pdispparams, VARIANT* pvarresult, EXCEPINFO* pexcepinfo, UINT* puargerr); //Funkce rozhraní IAuto HRESULT stdcall pocetkol(int *vysledek); private: ULONG m_cref; ITypeInfo* m_ptypeinfo; ; //počítadlo referencí //ukazatel na typové informace Implementaci funkcí rozhraní IUnknown již známe. Proto si teď popíšeme jednotlivé funkce rozhraní IDispatch.

Sdílení dokumentů ve stávajícím informačním systému 29 Funkce GetTypeInfoCount je volána klientem, pokud je komponenta schopna poskytnout typové informace. Výsledkem je jednoznačná odpověď ano / ne určené hodnotami 1 nebo 0. Důvodem proč může klient požádat o typové informace je realizace tzv. early binding (brzké vazby). Brzká vazba je opakem late binding (pozdní vazby). Když program zakládá instanci komponenty, musí ověřit, zda objekt existuje a jestli jsou funkce nebo vlastnosti použity správně. Brzká vazba nastává v době kompilace kódu a může urychlit jeho vykonávání. Pozdní vazba nutí program zjišťovat potřebné informace opakovaně v průběhu programu. Implementace funkce GetTypeInfoCount je velmi jednoduchá a vypadá takto: HRESULT Auto:: GetTypeInfoCount(UINT* pcounttypeinfo) { *pcounttypeinfo = 1; Return S_OK; Funkce GetTypeInfo je vyvolána, jakmile aplikace zjistí, že server je schopen poskytovat typové informace. Jejím účelem je vrátit ukazatel na typové informace o implementovaném rozhraní. Funkce získá v prvním parametru číslo rozhraní, jehož typové informace jsou vyžadovány. Jelikož naprostá většina komponent implementuje pouze jeden dispinterface, je platná hodnota 0. Druhý parametr určuje tzv. locale identifier, určující jazykovou variantu typových informací. Třetí parametr je ukazatel na poskytnutý výsledek. Implementace této funkce by mohla vypadat takto. HRESULT Auto:: GetTypeInfo(UINT itypeinfo, LCID lcid, ITypeInfo** ppitypeinfo) { *ppitypeinfo = NULL; if(itypeinfo!= 0) return DISP_E_BADINDEX; m_ptypeinfo->addref(); *ppitypeinfo = m_ptypeinfo; Return S_OK; Funkce GetIDsOfNames je jedna ze složitějších funkcí tohoto rozhraní. Jejím úkolem je přeložit jméno volané funkce na DISPID, neboli najít ve zvolené datové struktuře zmíněnou asociaci. Funkce má více parametrů a proto si je shrneme v tabulce Tab. 3. Parametr Význam riid Parametr není používán a musí mít vždy hodnotu IDD_NULL rgszname cnames lcid rgdispld Aby klient nemusel opakovaně volat tuto metodu, je možné najednou zadat pole jmen, pro které klient hledá odpovídající DISPID Tento parametr vyjadřuje počet položek v parametru rgszname Obsahuje konstantu popisující národní prostředí. Je pole s výslednými DISPID Tab. 3: Parametry funkce GetIDsOfNames Vlastní implementace této funkce je plně v rukou programátora. Jestliže je implementace složitá můžeme využít tuto implementaci: HRESULT Auto:: GetIDsOfNames(REFIID riid, LPOLESTR* rgsznames, UINT cnames, LCID lcid, DISPID* rgdispid) { if(riid!= IID_NULL) return DISP_E_UNKNOWNINTERFACE; return DispGetIDsOfNames(m_pTypeInfo, rgsznames, cnames, rgdispid);

Sdílení dokumentů ve stávajícím informačním systému 30 Funkce Invoke je poslední metodou rozhraní, která slouží ke spuštění funkcí na základě předaného DISPID. Její algoritmus najde v paměti implementaci požadované funkce a spustí ji. Její parametry si znovu vysvětlíme v tabulce Tab. 4. Parametr Význam displdmember V parametru je uložena hodnota DISPID volané funkce. riid Parametr je rezervován pro budoucí použití a musí mít hodnotu IID_NULL. Lcid Stejně jako u předchozích metod parametr udává zvolené národní prostředí wflags Parametr může nabývat pouze hodnot daných konstantami: DISPATCH_METHODE klient volá metodu rozhraní DISPATCH_PROPERTYGET klient čte hodnotu vlastností DISPATCH_PROPERTYPUT klient zapisuje do vlastností DISPATCH_PROPERTYGETREF vlastnost je změněna přiřazením pdispparams reference místo hodnoty. Jde o ukazatel na strukturu nazvanou DISPARAMS, obsahující parametry předávané metodě. pvarresult V parametru je uložena návratová hodnota. Není to přímo návratová hodnota funkce, ale jde o hodnotu parametru s atributem [out, retval]. pexcepinfo Parametr slouží k předání rozšířeného chybového hlášení. Obsahuje přesné informace o vzniklé chybě. puargerr Parametr umožňuje klientské aplikaci zjistit, proč nastala chyba při volání metody Invoke. Nedáme-li dostatečný počet parametru nebo je parametr špatného typu, není funkce zpuštěna a je vrácen chybový kód DISP_E_TYPEMISMATCH nebo DISP_E_PARAMNOTFOUND. Tab. 4: Parametry funkce Invoke Podobně jako u předchozí funkce můžeme volit mezi úplnou implementací a použitím již existující funkce DispInvoke, která je jednodušší variantou. Vše má své výhody a nevýhody. Jednodušší varianta nepodporuje rozšířené zpracování chyb a klientská aplikace nemůže využít předposledního parametru funkce. Následující kód ukazuje tělo funkce Invoke v jednodušší variantě. HRESULT Auto:: Invoke(DISPID dispidmember, RERIID riid, LCID lcid, WORD wflags, DISPPARAMS* pdispparams, VARIANT* pvarresult, EXCEPINFO* pexcepinfo, UINT* puargerr) { if(riid!= IID_NULL) return DISP_E_UNKNOWNINTERFACE; return DispInvoke(this, m_ptypeinfo, dispidmember, wflags, pdispparams, pvarresult, pexcepinfo, puargerr); 2.2.4 Detekce chyb Při použití libovolné komponenty může vzniknout mnoho chybových stavů. Jejich původ může být v těle funkcí samotných, jako je výskyt nepovolené hodnoty parametru, popřípadě nedostatek operační paměti pro vykonání algoritmu. Druhým velkým zdrojem chyb jsou služby COM, používané například pro vytvoření instance komponenty. Pokud není komponenta správně zaregistrovaná, nemůže dojít k jejímu zavedení do paměti a klient se musí o tomto dozvědět. Jednou z dalších chyb bývá nepovolený přístup ke vzdálenému počítači při použití technologie

Sdílení dokumentů ve stávajícím informačním systému 31 DCOM. Chyb je opravdu velké množství a o všech stavech komponenty musí být klientská aplikace informována. Všechny funkce rozhraní vracejí hodnotu typu HRESULT. Stejný typ návratové hodnoty má většina podpůrných COM API funkci, jako jsou CoCreateInstance nebo CoInitialize. Vrácení chybového stavu je lety prověřená metoda. Abychom mohli dekódovat chybové stavy, musíme těmto stavům porozumět. Analýza chybového kódu je velmi slabým místem uvedené techniky. Velmi často vede k zdlouhavým porovnáváním návratové hodnoty s různými konstantami, abychom dospěli k výsledku. Rozluštění obsahu návratového kódu může být jednoduchou záležitostí, ale i velmi dlouhým a časově náročným kódem. Záleží na hloubce informace, kterou se potřebujeme dozvědět. Pokud nám postačí jednoduchá odpověď, můžeme využít makropříkazy SUCCEEDED a FAILED. HRESULT hr = CoInitialezeEx(NULL, COINIT_APARTMENTTHREADED); if(failed(hr) cout << Klient: Nelze inicializovat apartment. << endl; hr = CoCreateInstance(CLSID_Auto, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**) &punknown); if(failed(hr) cout << Klient: Nelze zalozit instanci komponenty. << endl; Jestliže však potřebujeme zjistit podrobnější původ chyby, musíme individuálně testovat návratovou hodnotu funkce a to je velmi obtížné. Pokud chceme pouze informovat uživatele komponenty o příčinách chyby, můžeme použít funkci Win32 API, nazvanou FormatMessage. Funkce překládá chybový kód na textový popis, který můžeme dále použít. if(hresult_facility(hr) == FACILITY_WINDOWS) hr = HRESULT_CODE(hr); char* szerror; if(formatmessage(format_message_allocate_buffer FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&szError, 0, NULL)!= 0) { cout << Preklad chyby ( << hr << ): << szerror << endl; LocalFree(szError); else printf( Nezname cislo chyby\n );

Sdílení dokumentů ve stávajícím informačním systému 32 3 Základní COM objekty pro práci s Microsoft Office Firma Microsoft pro svůj produkt Microsoft Office, který se skládá z Microsoft Word, Microsoft Excel, Microsoft PowerPoint, Microsoft Outlook a Microsoft Access, vyvinula knihovnu, která je založena na základech COM technologie, přesněji řečeno na OLE Automation. Tato knihovna vznikla proto, aby si uživatelé nebo firmy mohli některé funkce upravit popřípadě úplně přeprogramovat. Dále se budu věnovat knihovně pro Microsoft Word a Microsoft Excel. Pro oba produkty je základní třída _Application. Dále pro Microsoft Word jsou velmi důležité třídy _Document a Documents a pro Microsoft Excel to je třída Workbooks. 3.1 Třída COleDispatchDriver Třída COleDispatchDriver je třída, od které dědí výše zmíněné třídy, všechny ostatní třídy v knihovnách Microsoft Word a Microsoft Excel, ale není to základní třída. Tato třída implementuje OLE Automation na straně klienta. OLE vystavuje rozhraní poskytující přístup k funkcím a vlastnostem objektu. Členské funkce této třídy připojují, oddělují, vytvářejí a uvolňují spojení s IDispatch. Její další funkce se používají pro proměnlivé argumenty, uložené v seznamu pro zjednodušení volání funkce Invoke z rozhraní IDispatch. Tuto třídu můžeme přímo používat, ale obyčejně se používá pouze, pokud byla vytvořena ClassWizardem. 3.1.1 Automation Clients Automation vytváří možnost pro naše aplikace manipulovat s objekty v dalších aplikacích nebo zjistit objekty, s kterými je možno manipulovat. Automation client je aplikace, která může manipulovat s nalezenými objekty současně s dalšími aplikacemi. Aplikace vyhledá objekty volané Automation server. Klient manipuluje se serverovými instancemi objektů, které zajišťují přístup k vlastnostem a funkcím těchto objektů. Máme dva typy. První je klient, který dynamicky získává informace o vlastnostech a operacích na serveru. Druhý je klient, který vlastní statické informace, které specifikují vlastnosti a operace na serveru. Klient prvního typu získá informace o serverových metodách a vlastnostech dotazem k rozhraní IDispatch. I když je to dostatečné použití dynamického klienta, IDispatch je obtížné použití pro statického klienta, kde objekt musí být znám již v době kompilace programu. Pro staticky vázaného klienta poskytla Microsoft Foundation classes třídu COleDispatchDriver společně s podporou ClassWizard. Staticky vázaný klient využívá prostředníky, takže staticky linkuje klientské aplikace. Tato třída poskytuje určitý druh bezpečí v C++, stručně vyjádřeno vlastnostmi a funkcemi serverových aplikací. Třída COleDispatchDriver poskytuje hlavní podporu klienta ze strany Automation. Použitím ClassWizard, můžeme vytvořit třídu odvozenou od COleDispatchDriver. Poté upřesníme typovou knihovnu souboru popsáním vlastností a