Zásuvný modul pro Microsoft Visual Studio. Pavel Plasz
|
|
- Michal Dušek
- před 7 lety
- Počet zobrazení:
Transkript
1 České vysoké učení technické v Praze Fakulta elektrotechnická ČVUT FEL katedra počítačů Bakalářská práce Zásuvný modul pro Microsoft Visual Studio Pavel Plasz Vedoucí práce: Ing. Tomáš Zahradnický Studijní program: Elektrotechnika a informatika strukturovaný bakalářský Obor: Informatika a výpočetní technika červenec 2007
2 ii
3 Poděkování Poděkovat bych chtěl především vedoucímu bakalářské práce Ing. Tomáši Zahradnickému za trpělivou pomoc při jejím psaní. Dále děkuji všem svým přátelům, kteří mě podporovali v psaní mého zatím nejrozsáhlějšího díla. iii
4 iv
5 Prohlášení Prohlašuji, že jsem svou bakalářskou práci vypracoval samostatně a použil jsem pouze podklady uvedené v přiloženém seznamu. Nemám závažný důvod proti užití tohoto školního díla ve smyslu 60 Zákona č. 121/2000 Sb., o právu autorském, o právech souvisejících s právem autorským a o změně některých zákonů (autorský zákon). V Praze dne v
6 vi
7 Abstract The bachelor thesis discusses Microsoft Visual Studio add-in module creation. A sample, step by step created add-in demonstrates the essentials of COM programming and extends the development environment with a new functionality. The resulting DLL library extends Microsoft Visual Studio by adding an option to convert source code from C/C++ language to the assembly language, which is consequently displayed. The add-in is easily accessible via a Disassemble command shown in the contextual menu of any C or CPP file in the Solution Explorer window. Abstrakt Bakalářská práce pojednává o tvorbě zásuvného modulu pro vývojové prostředí Microsoft Visual Studio. Vysvětlen je princip programování s využitím technologie COM na příkladu kompletního modulu vytvořeného jako součást této práce. Výsledný modul v podobě DLL knihovny rozšiřuje funkce Microsoft Visual Studia o možnost převést zdrojový kód z jazyka C/C++ do jazyka symbolických instrukcí a ten následně zobrazit. Akce je snadno přístupná jako položka Disassemble v rozevírací nabídce libovolného C nebo CPP souboru v okně Solution Explorer. vii
8 viii
9 Obsah Seznam obrázků a tabulek xi 1 Úvod 1 2 Analýza a návrh řešení Forma řešení Objektový soubor Převod do assembleru Uživatelské rozhraní Instalace Zásuvné moduly pro Microsoft Visual Studio Rozšiřitelnost (Visual Studio Extensibility) Makra Zásuvné moduly Komponentový model COM Rozhraní komponent Rozhraní IUnknown Počítání odkazů Identifikátor GUID Datový typ HRESULT Registrace komponent Chytré ukazatele Rozhraní IDispatch Hierarchie komponent Microsoft Visual Studia Vytváření zásuvného modulu Průvodce pro vytváření kostry add-inu Rozhraní _IDTExtensibility Přidávání prvků do uživatelského rozhraní (IDTCommandTarget) Reakce na události (IDispEventImpl) Registrace zásuvného modulu Implementace Microsoft Visual Studio 8.0 (2005) Inicializace zásuvného modulu (metoda CConnect::OnConnection()) Nastavení stavu ovládacího prvku (metoda CConnect::QueryStatus()) Provedení příkazu (metoda CConnect::Exec()) Třída CBuildEvents obsluhující překladové události Obsluha dokončení překladu (metoda CBuildEvents::OnBuildDone()) Microsoft Visual Studio 7.1 (2003) NSIS instalátor Závěr 29 6 Literatura 30 A Hierarchie komponent Microsoft Visual Studia 33 B Obsah přiloženého CD 34 ix
10 x
11 Seznam obrázků 2.1 Solution Explorer kontextová nabídka s položkou Disassemble Formát datového typu HRESULT Spuštění průvodce pro vytvoření add-inu Průvodce pro vytvoření add-inu - krok č Průvodce pro vytvoření add-inu - krok č Průvodce pro vytvoření add-inu - krok č Průvodce pro vytvoření add-inu - krok č Komponenty využívané zásuvným modulem Disassembler Ukázka použití zásuvného modulu Disassembler A.1 Hierarchie komponent Microsoft Visual Studia Seznam tabulek 3.1 Popis projektových souborů add-inu xi
12 xii
13 KAPITOLA 1. ÚVOD 1 1 Úvod Microsoft Visual Studio patří v současné době k jednomu z nejrozšířenějších vývojových prostředí pro platformu Microsoft Windows. Má mnoho funkcí, které usnadňují programátorům práci a umožňuje tvorbu rozsáhlých projektů. Distribuce Microsoft Visual Studia obsahuje kompilátory pro všechny programovací jazyky, které podporuje, tj. C/C++, C#, Visual Basic a J# z nichž dlouhodobě nejvíce používaným je jazyk C++. Hardwarová náročnost vyvíjené aplikace velmi záleží na programátorovi. To platí zejména u tzv. neřízeného kódu (unmanaged code), ve kterém se uvolňování paměti provádí explicitně ve zdrojovém kódu 1, a po přeložení do nativního kódu procesoru může program běžet rychleji. Pro vývojáře je proto důležité vědět, jak se jeho kód zapsaný v C/C++ překládá. Kvalita kódu je ovlivněna algoritmem a použitím vhodných klíčových slov, ale také nastavením přepínačů překladače. Kromě integrovaných kompilátorů od Microsoftu lze používat i jiné překladače, které produkují různý výsledný kód. Pro správné fungování přeloženého programu tedy nezáleží na tom jaký kód je vygenerován, stačí když překladač dodržuje ABI (Application Binary Interface), tj. specifikaci rozhraní mezi aplikací a operačním systémem, která definuje způsob předávání parametrů funkcím, vlastnosti datových typů, organizaci paměti, používání registrů procesoru a podobně. Například chceme-li efektivně provádět operace s vektory na procesorech Intel 2, je vhodné použít překladač Intel C++ Compiler a správně nastavit využívání SIMD (Single Instruction Multiple Data) instrukcí poskytovaných v rozšířeních SSE, SSE2, SSE3 a SSE4, což znamená dobře zvolit z více než sta přepínačů. Pro nalezení optimální konfigurace je potřeba reagovat na změny přeloženého kódu. Správným nastavením přepínačů lze docílit velmi výrazného zrychlení běhu vyvíjené aplikace. Sledováním přeloženého kódu je také možné odhalovat souběhové chyby (tzv. race condition). Například máme-li v programu cyklus podmíněný hodnotou proměnné, kterou uvnitř tohoto cyklu nijak neměníme, překladač považuje za zbytečné ji při každém testování číst z paměti a považuje ji za konstantu. Podmínka v cyklu je pak bud úplně vynechána (pokud by při porovnávání byla vždy splněna) anebo je vynechán celý cyklus (pokud by naopak nebyla splněna nikdy). Programátor ale očekává změnu proměnné v paměti způsobenou například jiným vláknem nebo obsluhou přerušení. Taková chyba by se ve zdrojovém kódu hledala špatně, ale při pohledu na procesorové instrukce vytvořené kompilátorem je chyba vidět okamžitě a lze ji ošetřit přidáním klíčového slova volatile k deklaraci proměnné. Příklad fragmentu kódu v jazyce C++ obsahující tuto souběhovou chybu (smyčka čeká na snížení hodnoty proměnné cislo v paměti): int cislo = 5, cislo2 = 0; while (cislo > 4) { cislo2 ++; } printf("%d", cislo2); V jazyce symbolických instrukcí po přeložení s nejvyšší optimalizační úrovní je kód uplně vynechán a provádí se pouze jednoduchá nepodmíněná smyčka: _main: : jmp _main 1 u řízeného kódu (managed code) provádí automatickou správu paměti tzv. Garbage Collector 2 procesory Intel jsou dnes běžně vícejádrové
14 2 KAPITOLA 1. ÚVOD Po přeložení se stejným nastavením, ale proměnná je deklarována volatile int cislo = 5, nedojde k vynechání kódu a cyklus skončí pokud bude proměnná v paměti snížena jiným vláknem: : mov dword ptr [esp+4], B: mov dword ptr [esp], : mov ecx,dword ptr [esp+4] : mov eax, B: cmp ecx,eax D: jle D F: nop : mov ecx,dword ptr [esp] : inc ecx : mov dword ptr [esp],ecx : cmp dword ptr [esp+4],eax B: jg D: xor eax,eax Na adrese instrukce cmp (compare) porovnává hodnotu proměnné cislo, což určuje zda následující instrukce jg provede skok zpět, tj. další iteraci cyklu. I přes vysoký stupeň optimalizace je díky klíčovému slovu volatile hodnota operandu instrukce cmp získávána vždy z paměti. Z kódu je také vidět, že použitý překladač Microsoft Visual Studia neoptimalizoval kód nejlépe, nebot například instrukce na adrese zbytečně kopíruje hodnotu proměnné cislo do registru, přitom následné porovnání mohlo být provedeno přímo s hodnotou z paměti. Přímé zobrazení přeloženého zdrojového kódu Microsoft Visual Studio neumožňuje. Umí ho zobrazit jen po spuštění programu, a to vždy celý kód vzniklý spojením všech zdrojových souborů pomocí linkeru. Navíc ve verzi 7.1 (2003), která je dnes stále hojně používaná, je zobrazení dosti nepřehledné (pouze čistý kód bez názvů funkcí). Naštěstí je toto vývojové prostředí modulární, skládá se z komponent COM[1] modelu a podporuje přidání vlastních COM objektů, které mohou implementovat nové funkce a využívat již existující komponenty. Bakalářská práce si klade za cíl tento nedostatek ve Visual Studiu opravit vytvořením zásuvného modulu. Cílem zásuvného modulu je umožnit programátorovi kdykoliv snadno zjistit jak bude přeložený zdrojový kód vypadat v jazyce symbolických instrukcí assembleru.
15 KAPITOLA 2. ANALÝZA A NÁVRH ŘEŠENÍ 3 2 Analýza a návrh řešení 2.1 Forma řešení Při vyvíjení aplikace v Microsoft Visual Studiu může vzniknout potřeba vidět výstup kompilátoru celkem často. Při psaní částí kódu, které pracují s větším objemem dat, nebo cyklů s velkým počtem iterací záleží na každé instrukci, kterou bude procesor provádět. Při každé změně algoritmu nebo při změně nastavení kompilátoru je dobré zjistit zda došlo ke zlepšení efektivity přeloženého programu, tj. zda vykonání stejné požadované operace vyžaduje méně systémových prostředků. Pro přesné analyzování výkonu vyvíjeného programu se používají tzv. profilery. Profilerů je celá řada a fungují na různých principech měření. Například profilery na principu vzorkování zjišt ují v pravidelných časových intervalech o kolik se zvýšil čítač programových instrukcí (program counter) a podle toho pak lze odhalit, v kterých místech se program nejvíce zdržel. Dalším způsobem analýzy je měření času trvání provádění podprogramů profiler reaguje na instrukce volání a návratu z podprogramu a je schopen vypočítat jak velkou poměrnou část času běhu programu jednotlivé podprogramy trvaly. Pro optimalizaci programu je výhodné sledovat nejnáročnější části kódu v jazyce symbolických instrukcí a ty pak vhodně upravit. Zobrazení přeloženého kódu by tedy mělo být snadno přístupné a jednoduché, aby programátora zbytečně nezdržovalo. Používání další aplikace je zbytečně složité, a proto ideálním řešením, které Microsoft Visual Studio nabízí, je forma zásuvného modulu pracujícího na principu technologie COM (tzv. add-inu). Výhodou COM modelu je možnost využití komponent, které jsou již součástí vývojového prostředí. Konkrétně pro získání kódu v jazyce assembler je potřeba nejprve objektový soubor (object file), který vznikne kompilací zdrojového souboru v jazyce C/C++. Pro provedení kompilace lze využít komponentu Microsoft Visual Studia včetně jejího nastavení ve vývojovém prostředí, což zaručuje překlad stejný jako při vývoji. 2.2 Objektový soubor Objektový soubor obsahuje především instrukce a data přeloženého souboru v binární podobě. Dále soubor obsahuje tabulku se seznamem míst v objektovém kódu, na kterých se vyskytuje přímá adresace paměti (například instrukce skoku nebo load/store instrukce) nebo volání podprogramů definovaných v jiných zdrojových souborech, jejichž adresy zatím nejsou známy. Při spojování více objektových souborů linkerem jsou tyto adresy dopočítány tak, aby odkazovaly na odpovídající části kódu ve výsledném souboru. Neméně důležitou součástí souboru jsou ladící informace (debug information) jako je tabulka globálních symbolů definovaných ve zdrojovém souboru, lokální symboly, čísla řádek původního zdrojového kódu a případně i další informace. 2.3 Převod do assembleru Instrukce a operandy v objektovém souboru jsou v binárním tvaru a těžko by se v nich programátor vyznal, proto je nutné je převést do čitelné podoby v jazyce symbolických instrukcí assembleru. Například instrukce ve strojovém kódu procesorů Intel x86/i386[7] bude převedena na instrukci assembleru mov al, 61h Provádění tohoto převodu není předmětem bakalářské práce, místo toho lze s výhodou využít např. externí programy nm[6] nebo objdump[6], které jsou pod GNU licencí a jejich použití je
16 4 KAPITOLA 2. ANALÝZA A NÁVRH ŘEŠENÍ zdarma. Vhodnější ale bude použít program dumpbin[3], který je součástí distribuce Microsoft Visual Studia, a také umožňuje převod do jazyka symbolických instrukcí. Do výstupu, který tento program produkuje, ještě přidává označení názvů funkcí, jejichž tělo je v assembleru zobrazeno, což zlepšuje orientaci v kódu. Názvy symbolů jsou získávány taktéž z objektového souboru. Vygenerovaný kód je zapisován do souboru s názvem shodným se zdrojovým souborem s příponou ASM. 2.4 Uživatelské rozhraní Spuštění překladu, následné převedení do assembleru a zobrazení bude přístupné kliknutím na položku Disassemble, která bude k dispozici v kontextové nabídce každého projektové souboru s příponou C, nebo CPP. V Microsoft Visual Studiu jsou všechny soubory vyvíjeného projektu zobrazeny v okně Solution Explorer, kde jsou rozdělené do kategorií a dále ve stromové struktuře podle složek, v kterých jsou umístěny. Snadno zde vybereme požadovaný soubor, na kterém kliknutím pravým tlačítkem myši vyvoláme jeho nabídku proveditelných akcí. Vytvořený kód se zobrazí otevřením ASM souboru přímo v textovém editoru Microsoft Visual Studia. Obrázek 2.1: Solution Explorer kontextová nabídka s položkou Disassemble
17 KAPITOLA 2. ANALÝZA A NÁVRH ŘEŠENÍ Instalace Zásuvné moduly pro Microsoft Visual Studio jsou uloženy jako dynamicky linkované knihovny, které poskytují COM servery. Knihovnu je před použitím nutné zaregistrovat, aby ji mohlo vývojové prostředí využívat. K tomu lze využít program regsvr32, který je součástí operačního systému Microsoft Windows. Více o registraci COM serverů je popsáno v následující kapitole. Pro Microsoft Visual Studio verze 7.1 (2003) je navíc nutné přidat záznam do registrů Windows, aby se add-in objevil ve správci zásuvných modulů a bylo možné jej aktivovat. Dále je před používáním add-inu nutné vytvořit dávkový soubor, který bude nastavovat hodnotu systémové proměnné PATH a spustí program dumpbin se správnými parametry. Verze DLL knihovny a obsah dávkového souboru jsou pro Microsoft Visual Studio ve verzi 7.1 (2003) a verzi 8.0 (2005) odlišné a je nutné je volit podle hodnot zjištěných v registrech Windows. Aby toto všechno proběhlo automaticky a uživatel add-inu jej mohl snadno začít používat, je rozumné využít instalátor, který provede výše uvedené akce sám. Vhodným řešením je NSIS (Nullsoft Scriptable Install System)[4], který umožňuje zkopírování a registraci DLL knihovny, čtení a zápis do registrů Windows, větvení na základě přečtených hodnot i zápis do textového souboru (pro vytvoření dávky), tedy vše potřebné pro instalaci zásuvného modulu i většiny dalších aplikací. Navíc je zcela zdarma pro libovolné použití.
18 6 KAPITOLA 3. ZÁSUVNÉ MODULY PRO MICROSOFT VISUAL STUDIO 3 Zásuvné moduly pro Microsoft Visual Studio 3.1 Rozšiřitelnost (Visual Studio Extensibility) Přestože Microsoft Visual Studio poskytuje velké množství funkcí, při vývoji nejrůznějších projektů je někdy potřeba provádět akce, které toto vývojové prostředí umožňuje řešit provedením několika dílčích kroků, případně s nutností využít další vývojářské nástroje. V případech, kdy by se takových kroků mělo provádět více a celý sled akcí by se vícekrát opakoval, je výhodnější takový proces vhodným způsobem automatizovat a rozšířit Microsoft Visual Studio o možnost provádět takové úlohy automaticky. Microsoft Visual Studio nabízí dvě základní metody rozšíření makra a zásuvné moduly Makra Vytvoření makra je ve Visual Studiu podobné jako u většiny jiných aplikací podporujících makra. Jednoduše se spustí zaznamenávání, pak se provede sled akcí, které se mají automatizovat, a zaznamenávání se ukončí. Jednotlivé kroky jsou uloženy v podobě příkazů jazyka Visual Basic. Zaznamenané makro pak můžeme kdykoliv spustit a proces je opět proveden, například s jiným dokumentem. Tento způsob je velmi snadný a rychlý a v některých případech zcela dostačující, nicméně možnosti nejsou tak široké jako při použití zásuvného modulu Zásuvné moduly Zásuvný modul je dynamická knihovna provádějící operace pro program, který ji používá. Z pohledu uživatele se ovládání funkcí poskytovaných zásuvným modulem nemusí nijak lišit od ovládání základního programu. Ve skutečnosti Visual Studio jako celek je složeno z mnoha dílčích komponent, které spolu vzájemně komunikují a jsou využívány klientskou aplikací, která nám poskytuje uživatelské rozhraní. Add-in je tedy přídavná komponenta k modulární aplikaci, v našem případě k Microsoft Visual Studiu fungujícím na technologii COM. 3.2 Komponentový model COM COM (Component Object Model) je specifikace určující jakým způsobem vytvářet aplikace skládájící se z více nezávisle pracujících modulů COM komponent. COM komponenty obsahují proveditelný kód v podobě dynamicky linkované knihovny (typicky s příponou DLL), nebo jako spustitelný soubor (s příponou EXE)[5]. Aplikace složená z COM komponent umožňuje uživateli pracovat více podle jeho představ, nebot může volit z více komponent poskytujících podobné služby, instalovat nové moduly rozšiřující aplikaci o nové funkce nebo naopak v nové aplikaci využívat komponentu, na kterou je již zvyklý z jiného programu (typickým příkladem je textový editor použitý v různých aplikacích, který se může vyvíjet nezávisle). Kdybychom například chtěli vyvíjet aplikaci obsahující prohlížeč webových stránek, stačí připojit komponentu Internet Explorer k našemu programu a předávat jí URL požadovaného HTML dokumentu. Komponenta prohlížeče již sama provede načtení dat a zobrazení stránky. Pokud je splněna specifikace COM je zaručeno, že komponenty spolu budou umět pracovat. Komponenty mohou být vyvíjeny v téměř libovolném procedurálním programovacím jazyku, nebot se distribuují vždy přeložené v binárním tvaru. Pro správné fungování COM komponent je nutné dodržet dvě základní podmínky. Komponenty vždy musí být linkovatelné dynamicky, tj. kód jimi poskytovaných služeb se do paměti nahrává až když je potřeba a po jeho použití je možné jej z paměti odstranit. To je důležité, nebot statické linkování by vyžadovalo přelinkování celého programu a jednotlivé moduly by
19 KAPITOLA 3. ZÁSUVNÉ MODULY PRO MICROSOFT VISUAL STUDIO 7 se pak nemohly nezávisle vyvíjet. Dynamické linkování umožňuje připojovat komponenty za běhu aplikace a navíc může šetřit pamět. Aby mělo dynamické linkování smysl a bylo možné libovolnou komponentu odpojit a nahradit ji za jinou bez nutnosti znovu kompilovat a linkovat celou aplikaci, je nutné kód komponenty zapouzdřit, tj. skrýt vlastní kód komponenty za určité jednotné rozhraní, přes které se k ní program nebo jiná komponenta připojuje. Pokud takové rozhraní zůstane zachováno, připojovaná komponenta se může jakkoliv změnit a program ji bude moci nadále používat Rozhraní komponent Aby se program nebo komponenta, tzv. COM klient, mohl připojit k jiné komponentě, tzv. COM serveru, a mohl ji začít využívat, musí s ní umět komunikovat. Interakce mezi COM objekty je umožněna pomocí COM rozhraní, což je vlastně struktura v paměti obsahující pole ukazatelů na funkce implementované komponentou. V jazyce C++ jsou rozhraní tvořeny abstraktní třídou, jejíž virtuální metody jsou implementovány v potomcích. Třída komponenty tedy musí být potomkem nějakého rozhraní, případně může být zděděna i z více rozhraní najednou. Naopak více komponent může dědit ze stejného rozhraní a díky polymorfismu tak získáme možnost manipulovat stejným způsobem s různými komponentami[2], což je právě ta stěžejní vlastnost COM modelu, která umožňuje nahrazovat komponenty za jiné, ke kterým se přistupuje shodně. V praxi při tvorbě modulárních aplikací vzniká celá hierarchie tříd, které definují různá rozhraní. Implementace těchto rozhraní je již formou COM objektů, které lze nezávisle zaměňovat. Uživatel možnost změny komponenty vždy mít nemusí, ale aplikace může této vlastnosti sama využívat pro svou aktualizaci, nebot se nemusí nahrazovat celá, ale pouze modifikované komponenty Rozhraní IUnknown Rozhraní IUnknown musí být předkem všech definovaných rozhraní, což zaručí, že každá COM komponenta bude implementovat jeho virtuální metody AddRef(), QueryInterface() a Release(). Rozhraní IUnknown je definováno takto: class IUnknown { public: virtual HRESULT stdcall QueryInterface( const IID& iid, void** ppv ) = 0; virtual ULONG stdcall AddRef() = 0; virtual ULONG stdcall Release() = 0; }; Metody AddRef() a Release() budou vysvětleny v sekci Metoda QueryInterface() slouží k získání ukazatele na požadované rozhraní. Každý COM objekt musí tuto metodu implementovat tak, aby pomocí ní bylo možné získat libovolné požadované rozhraní, které komponenta implementuje. Prvním parametrem určíme jaké rozhraní potřebujeme, druhý parametr je výstupní a v případě úspěchu obsahuje ukazatel na dotazované rozhraní. Abychom mohli volat metodu QueryInterface() je potřeba nejdříve vytvořit instanci COM objektu. Vytváření instance musí probíhat na straně COM serveru, nebot klient vůbec implementační třídu nezná. Pokud bychom sami připojovali komponentu načtením dynamické knihovny, řešením by bylo volat vhodně vytvořenou statickou metodu exportovanou knihovnou, která by vytvořila instanci COM objektu a vrátila by ukazatel na ni přetypovaný na IUnknown*. Díky polymorfismu klient může pomocí získaného ukazatele na rozhraní IUnknown získávat ukazatele na další implementovaná rozhraní a komponentu ovládat. V praxi je výhodnější použít funkci COM knihovny s názvem CoCreateInstance(), která je deklarována takto:
20 8 KAPITOLA 3. ZÁSUVNÉ MODULY PRO MICROSOFT VISUAL STUDIO HRESULT stdcall CoCreateInstance( const CLSID& clsid, IUnknown * piunknownouter, DWORD dwclscontext, const IID& iid, void ** ppv ); Prvním parametrem je clsid, což je unikátní identifikátor komponenty. Druhý parametr je ukazatel na rozhraní IUnknown vnější komponenty, které má být zpřístupněna vnitřní komponenta se zadaným CLSID. Tímto způsobem 1 se nahrazuje dědičnost, která mezi COM objekty není možná běžnými konvencemi C++ (nebot technologie COM je jazykově nezávislá). Třetí parametr dwclscontext určuje zda se bude kód komponenty provádět ve stejném procesu jako klient, nebo v jiném procesu na lokálním počítači, nebo v jiném procesu vzdáleně. Čtvrtý parametr iid je identifikátor rozhraní, kterým chceme s komponentou pracovat. Poslední parametr je výstupní a při úspěchu obsahuje ukazatel na hledané rozhraní. Návratová hodnota typu HRESULT je nastavena v případě úspěšného nalezení rozhraní na S_OK, v opačném případě na hodnotu konstanty popisující chybu. Funkce CoCreateInstance() nejprve vyhledá záznam v registrech Windows odpovídající zadanému CLSID a zjistí potřebné informace 2 o komponentě, na základě kterých načte dynamickou knihovnu do paměti a vytvoří instanci COM objektu. Pak se pomocí metody QueryInterface() dotazuje komponenty na rozhraní s identifikátorem IID, které je vráceno v pátém parametru funkce Počítání odkazů Vytvořenou instanci komponenty je vhodné odstranit z paměti, pokud již přestane být zapotřebí, tj. pokud již neexistuje žádný odkaz na některé z rozhraní, která komponenta implementuje. Aby COM objekt měl přehled o tom, zda existuje odkaz na některé z jeho rozhraní, využívá metodu zvanou počítání odkazů (reference counting), tj. komponenta si udržuje v proměnné počet existujících odkazů. Každá funkce, která vrací ukazatel na rozhraní komponenty (minimálně QueryInterface() je takovou funkcí), musí volat metodu komponenty AddRef(), která inkrementuje hodnotu počtu odkazů. Pokud klient již použité rozhraní nepotřebuje, měl by volat metodu Release(), která hodnot počtu odkazů sníží a v případě, že dosáhne nulové hodnoty, postará se o odstranění instance COM objektu z paměti. Implementace metod AddRef() a Release() je vyžadována při tvorbě komponenty z důvodu dědění z rozhraní IUnknown. Následující příklad zdrojového kódu v jazyce C++ znázorňuje vytvoření dvou COM rozhraní a komponenty, která tyto rozhraní implementuje. Z ukázky je patrný princip počítání odkazů a možný způsob implementace metod rozhraní IUnknown. Názvy rozhraní začínají písmenem I (interface) a názvy tříd s implementací písmenem C (class), což odpovídá konvencím programování COM aplikací. 1 tato metoda se nazývá aggregation 2 informace uložené v registrech Windows jsou detailněji popsány v sekci 3.2.6
21 KAPITOLA 3. ZÁSUVNÉ MODULY PRO MICROSOFT VISUAL STUDIO 9 Nejprve ukázka definice COM rozhraní: class IZvire : public IUnknown { public: virtual int stdcall get_rasa() = 0; }; class IVzhled : public IUnknown { public: virtual int stdcall get_barva() = 0; }; Fragment třídy implementující rozhraní IZvire a IVzhled: class CKocka : public IZvire, public IVzhled { public: CKocka() { m_cref = 0; } virtual ~CKocka() { } virtual int stdcall get_rasa() { return R_KOCKA_DIVOKA; } virtual int stdcall get_barva() { return B_CERNA; } // metoda pro získání ukazatele na implementované rozhraní virtual HRESULT stdcall QueryInterface( const IID& iid, void** ppv ) { if (iid == IID_IUnknown) { *ppv = (IUnknown *) this; } else if (iid == IID_IZvire) { *ppv = (IZvire *) this; } else if (iid == IID_IVzhled) { *ppv = (IVzhled *) this; } else { *ppv = NULL; return E_NOINTERFACE; } ((IUnknown *) *ppv)->addref(); return S_OK; } // zvýšení počtu existujících odkazů na rozhraní virtual ULONG stdcall AddRef() { return InterlockedIncrement(&m_cRef); } // snížení počtu existujících odkazů na rozhraní // a případné odstranění objektu z paměti virtual ULONG stdcall Release() { if (InterlockedDecrement(&m_cRef) == 0) { delete this; return 0; } return m_cref; } protected: long m_cref; };
22 10 KAPITOLA 3. ZÁSUVNÉ MODULY PRO MICROSOFT VISUAL STUDIO Pro zajištění atomicity zvyšování a snižování hodnoty proměnné m_cref jsou použity Win32 API funkce InterlockedIncrement() a InterlockedDecrement(), které umožní přístup k proměnné m_cref vždy jen jednomu vláknu. Implementace rozhraní mohou být libovolné, například rozhraní IVzhled může implementovat komponenta CAutomobil a klient používající toto rozhraní je schopen stejným způsobem zjistit barvu jak kočky, tak automobilu, aniž by věděl další informace o konkretní připojené komponentě. Pro kompletnost ještě demonstrace použití komponenty z příkladu (předpokladem je registrace COM serveru v operačním systému, aby funkce CoCreateInstance() mohla komponentu načíst a vytvořit její instanci): int rasa, barva; IZvire * pizvire = NULL; if (SUCCEEDED(CoCreateInstance(CLSID_Kocka, NULL, CLSCTX_INPROC_SERVER, IID_IZvire, (void **) &pizvire))) { rasa = pizvire->get_rasa(); IVzhled * pivzhled = NULL; if (SUCCEEDED(pIZvire->QueryInterface(IID_IVzhled, (void **) &pivzhled))) { barva = pivzhled->get_barva(); pivzhled->release(); } pizvire->release(); } Nejprve je funkcí CoCreateInstance() vytvořena instance COM komponenty s identifikátorem CLSID_Kocka a získáno rozhraní, které je poté použito k volání metody komponenty. Zda získání rozhraní proběhlo úspěšně je zjištěno pomocí makra SUCCEEDED(), které testuje návratovou hodnotou typu HRESULT. Následně je metodou QueryInterface() získáno další implementované rozhraní a to je také použito. Nakonec postupným voláním metody Release() jsou uvolněny oba odkazy na rozhraní a provedena destrukce objektu Identifikátor GUID Již zmiňované identifikátory rozhraní (IID) a identifikátory komponent (CLSID) jsou datové typy GUID. GUID (globally unique identifier) je 128-bitová struktura, která je globálně unikátní a lze pomocí ní určit jedno konkrétní rozhraní nebo komponentu na celém světě. Při vývoji nové komponenty nebo rozhraní je potřeba použít takový identifikátor GUID, který ještě neexistuje. K tomuto účelu slouží program guidgen, který vygeneruje unikátní klíč. Aby byla zajištěna jednoznačnost místa i času, 48 bitů z generovaného GUID obvykle odpovídá adrese sít ové karty v počítači, na kterém je guidgen spuštěn. Dalších 60 bitů kódu reprezentuje počet 100-nanosekundových intervalů od 15. října Zbývajících 20 bitů je generováno náhodně. Program guidgen je součástí Microsoft Visual Studia ve verzi dialogové i konzolové aplikace (uuidgen).
23 KAPITOLA 3. ZÁSUVNÉ MODULY PRO MICROSOFT VISUAL STUDIO Datový typ HRESULT Datový typ HRESULT je 32-bitové číslo nesoucí informaci o úspěšnosti vykonávané funkce. Hodnota HRESULT je rozdělena do tří částí: Obrázek 3.1: Formát datového typu HRESULT Nejvýznamnější je první bit nazývaný Severity, který indikuje zda došlo k chybě. Pokud je hodnota 0, znamená to úspěšné provedení funkce. Hodnota 1 označuje, že došlo k chybě, která je blíže specifikována v dalších částech. Následujících 15 bitů je označováno jako Facility a představují identifikátor části systému, která vrací návratový kód obsažený ve zbývajících 16 bitech. Microsoft definuje univerzální hodnoty facility kódů v souboru WINERROR.H (například FACILITY_WIN32, FACILITY_RPC, atd.). Poslední 16-bitová část obsahuje již zmiňovaný návratový kód (Return Code), který přesně specifikuje chybu, a opět používá hodnoty definované v souboru WINERROR.H. Kromě návratových kódů definovaných Microsoftem je možné definovat vlastní kódy, které nemusí být unikátní globálně, ale pouze v rámci rozhraní, které ho vrací. Vlastní návratové kódy musí mít v hodnotě HRESULT obsažen Facility kód FACILITY_ITF, což indikuje, že návratový kód je závislý na rozhraní. Pro jednoduchou práci s hodnotou typu HRESULT, aniž bychom si museli pamatovat jaká hodnota severity bitu označuje úspěch či neúspěch, slouží makra SUCCEEDED() a FAILED(), která již podle názvu napovídají o svém významu. Makro SUCCEEDED() nabývá hodnoty true pokud je hodnota HRESULT nezáporné číslo. Makro FAILED() je true pro záporné číslo (chyba) Registrace komponent Pro připojení COM komponenty do klientské aplikace je potřeba načíst dynamicky linkovanou knihovnu, což se v praxi provádí nejčastěji použitím funkce CoCreateInstance(), které předáme identifikátor CLSID určující vyžadovanou komponentu. Pro načtení souboru knihovny je potřeba, aby komponenta byla registrována v operačním systému, tj. aby měla záznam v registrech Windows obsahující informaci o umístění a názvu DLL souboru. Automatickou registraci lze provést pomocí programu regsvr32, který volá funkci DllRegisterServer(), kterou musí knihovna implementovat a exportovat. Stejným způsobem lze program použít pro zrušení registrace s využitím funkce DllUnregisterServer(). Implementace funkce DllRegisterServer() závisí na autorovi komponenty, nicméně musí dodržet strukturu záznamu, který přidává do registrů Windows. Pro práci s registry existují Win32 API funkce, které jsou přístupné po vložení hlavičkového souboru WINREG.H do zdrojového kódu a přilinkování souboru ADVAPI32.LIB. Informace o COM komponentách se v registrech ukládájí do větve HKEY_CLASSES_ROOT (HKCR) do klíče CLSID, jehož podklíče jsou veškeré registrované CLSID identifikátory v operačním systému. Každý CLSID klíč obsahuje jako svou výchozí hodnotu název komponenty, dále obsahuje podklíče InprocServer32, ProgID, VersionIndependentProgID a další. Nejdůležitější je klíč InprocServer32, který musí být nastaven vždy, když je komponenta tzv. in-proc server, tj. nahrává se do procesu COM klienta, kterému poskytuje své služby. Výchozí hodnota klíče InprocServer32 je úplná cesta umístění souboru DLL knihovny komponenty. ProgID je řetězec mapovaný na klíč CLSID, který je pro programátora lépe čitelný, ale není u něj zaručena
24 12 KAPITOLA 3. ZÁSUVNÉ MODULY PRO MICROSOFT VISUAL STUDIO unikátnost. Využívá se například k identifikaci komponent při vývoji v jazyce Visual Basic. Formát ProgID je podle konvencí COM ve tvaru Program.Komponenta.Verze, ale nebývá to vždy dodrženo. Například komponenta vyvíjená v této bakalářské práci svou registrací vytvoří záznamy v registrech takto: Files\\Disassembler add-in for Visual Studio\\Disassembler.dll" Chytré ukazatele Chytrý ukazatel (Smart Pointer) je třída, která přetěžuje operátor ->, aby vracel hodnotu ukazatele na jiný objekt. Použití chytrého ukazatele je stejné jako použití běžného ukazatele v C++, navíc ale třída chytrého ukazatele může provádět další operace s objektem, na který ukazuje. V případě chytrého ukazatele na COM rozhraní jeho třída implementuje metodu počítání odkazů, tj. konstruktor volá metodu AddRef() komponenty a destruktor metodu Release(), automaticky je volána metoda QueryInterface() v těle kopírujícího konstruktoru a při přiřazení hodnoty z jiného rozhraní. Při práci s COM rozhraním již není potřeba volat metodu Release(), o uvolňování komponent z paměti se třída chytrého ukazatele postará sama. Chytrý ukazatel na rozhraní definovaný jako šablona třídy lze použít univerzálně k libovolnému rozhraní, stačí pouze předat název třídy jako parametr šablony při jeho deklaraci. Knihovna ATL (ActiveX Template Library) nabízí dvě generické třídy chytrých ukazatelů pro usnadnění práce s COM rozhraními CComPtr a CComQIPtr. Typicky se používají jako staticky deklarované objekty, které se zruší na konci bloku a jejich destruktor provede uvolnění rozhraní Rozhraní IDispatch Kromě možnosti pracovat s komponentou přes COM rozhraní, které s ní přímo komunikuje, existuje další způsob nazývaný Automation. Je také postaven na COM architektuře a je tvořen tzv. Automation serverem, což je COM komponenta implementující rozhraní IDispatch, přes které s ní komunikuje tzv. Automation controller, což je COM klient. Funkce COM serveru nejsou klientem volány přímo, ale pomocí členských metod rozhraní IDispatch. Nejdůležitějšími funkcemi, které rozhraní IDispatch poskytuje jsou GetIDsOfNames() a Invoke(). Funkci GetIDsOfNames() se v parametru předá název funkce komponenty, kterou chce COM klient provést, a vrácena je hodnota typu DISPID (Dispatch ID), což je číslo identifikující hledanou funkci. HRESULT GetIDsOfNames( REFIID riid, OLECHAR FAR* FAR* rgsznames, unsigned int cnames, LCID lcid, DISPID FAR* rgdispid ); První parametr riid je rezervován pro budoucnost a zatím musí být vždy nastaven na IID_NULL. Druhý parametr rgsznames je pole názvů požadovaných funkcí, jejichž počet je předán v dalším parametru cnames. Následuje lcid, kterým se volí lokalizace názvů. Například
25 KAPITOLA 3. ZÁSUVNÉ MODULY PRO MICROSOFT VISUAL STUDIO 13 lze použít hodnotu vrácenou funkcí GetUserDefaultLCID(), což odpovídá lokalizačnímu nastavení uživatele v operačním systému. Poslední parametr rgdispid je výstupní a při úspěchu bude obsahovat DISPID. Pro provedení funkce se získaným DISPID slouží metoda Invoke(). HRESULT Invoke( DISPID dispidmember, REFIID riid, LCID lcid, WORD wflags, DISPPARAMS FAR* pdispparams, VARIANT FAR* pvarresult, EXCEPINFO FAR* pexcepinfo, unsigned int FAR* puargerr ); První parametr je DISPID identifikující funkci, kterou chce klient volat. Dále je opět rezervovaný parametr riid, který je nutno nastavit na IID_NULL, a parametr lcid pro nastavení lokalizace. Čtvrtý parametr wflags určuje v jakém kontextu má být funkce volána. Může být volána jako běžná metoda, nebo jako funkce pro získání či nastavení vlastnosti objektu, která má název odpovídající zadanému názvu při předchozím volání metody GetIDsOfNames(). Následující parametr pdispparams je ukazatel na strukturu obsahující pole argumentů, které se mají předat volané funkci. Šestý parametr pvarresult je ukazatel na datový typ VARIANT, v kterém bude uložen výsledek vrácený volanou funkcí. V parametru pexcepinfo bude uložena informace o výjimce, pokud nějaká vznikne, což je indikováno hodnotou HRESULT vrácenou metodou Invoke(). V případě výjimky bude vráceno DISP_E_EXCEPTION, v ostatních případech struktura EXCEPINFO nebude naplněna. Poslední parametr puargerr, pokud Invoke() vrátí hodnotu DISP_E_PARAMNOTFOUND nebo DISP_E_TYPEMISMATCH, bude nastaven na index argumentu, který vyvolal chybu, tj. bud chyběl nebo byl nesprávného datového typu. Libovolné z posledních tří parametrů lze nastavit na NULL v případě, že klient takovou informaci získat nepotřebuje. Další metoda rozhraní IDispatch s názvem GetTypeInfo() slouží k zjišt ování informací o datových typech parametrů, které jsou předávány funkci vykonávané metodou Invoke(). Princip používání komponenty přes rozhraní IDispatch je jednoduchý. Stačí vytvořit instanci komponenty a získat ukazatel na rozhraní IDispatch, což lze provést obvyklým způsobem pomocí funkce CoCreateInstance(), a pak již kombinací metod GetIDsOfNames() a Invoke() vykonávat funkce komponenty na základě jejich názvu. Komponenta tedy nemusí implementovat žádné další rozhraní mimo IDispatch, nebot je dostačující pro ovládání všech metod COM serveru. Implementace metod rozhraní IDispatch může být realizována pomocí tzv. typové knihovny (type library), což je komponenta, která přes rozhraní ITypeLib poskytuje informace o metodách a vlastnostech Automation serveru získané z přeloženého IDL souboru. IDL soubor má podobný význam jako hlavičkové soubory v C++, ale je zapsán v jazyce MIDL 3 (Microsoft Interface Definition Language) a jeho přeložená podoba se distribuuje spolu s knihovnou komponenty (může být dokonce obsažena v DLL souboru). Vyvíjená komponenta při své inicializaci načte svou typovou knihovnu a v implementaci metod GetIDsOfNames() a Invoke() použije její metody totožného názvu a významu. Předpokládejme, že dříve uvedenená demonstrační komponenta CKocka nyní implementuje rozhraní IDispatch a informace o jejích metodách jsou poskytovány její typovou knihovnou. Použití komponenty pomocí metod rozhraní IDispatch se od přímého volání přes IZvire a 3 jazyk určený speciálně k definici rozhraní komponent, který je nezávislý na programovacím jazyku, ve kterém je vyvíjena komponenta
26 14 KAPITOLA 3. ZÁSUVNÉ MODULY PRO MICROSOFT VISUAL STUDIO IVzhled bude výrazně lišit (pro větší přehlednost je v ukázce vynecháno testování návratových hodnot typu HRESULT): CLSID clsid; DISPID dispid; CLSIDFromProgID(L"Program1.Kocka", &clsid); IDispatch * pidispatch = NULL; CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IDispatch, (void **) &pidispatch); VARIANT pvarres; OLECHAR * nazevfunkce = L"get_Barva"; pidispatch->getidsofnames(iid_null, &nazevfunkce, 1, GetUserDefaultLCID(), &dispid); DISPPARAMS bezparametru = { NULL, NULL, 0, 0 }; pidispatch->invoke(dispid, IID_NULL, GetUserDefaultLCID(), DISPATCH_METHOD, &bezparametru, &pvarres, NULL, NULL); Identifikátor komponenty CLSID je získán z ProgID funkcí CLSIDFromProgID(), poté je vytvořena instance komponenty a obdržen ukazatel na IDispatch. Metodou GetIDsOfNames() je získán DISPID jediné funkce s názvem get_barva. Následuje založení struktury DISPPARAMS, kterou se předají argumenty požadované funkci v tomto případě žádné nevyžaduje. Nakonec je volána metoda Invoke(), která zajistí provedení funkce get_barva a vrácení výsledku v podobě datového typu VARIANT. Funkce CLSIDFromProgID() slouží k zjišt ování CLSID identifikátorů komponenty z jejího ProgID. V registrech Windows ve větvi HKEY_CLASSES_ROOT jsou umístěny klíče s názvy ProgID všech komponent registrovaných v operačním systému. Hodnota CLSID je zapsána jako výchozí hodnota podklíče s názvem CLSID. Naopak pro zjišt ování hodnoty ProgID podle identifikátoru CLSID lze použít funkci ProgIDFromCLSID() s využitím položky ProgID v registrech popsané v sekci Hierarchie komponent Microsoft Visual Studia Microsoft Visual Studio je modulární aplikace založená na technologii COM. Jednotlivé dílčí celky (COM komponenty) mají za úkol zpracovávat množinu souvisejících úloh a k tomu mohou využívat další komponenty, které mohou využívat další a další. Takto vzniká velká hierarchie (viz. obrázek v dodatku A), která dohromady tvoří aplikaci Microsoft Visual Studio. Chceme-li vytvořit zásuvný modul, který tuto architekturu rozšíří, je nezbytné mít přehled o rozhraních, přes která je možné s komponentami Microsoft Visual Studia pracovat. Pro získání rozhraní při programování zásuvného modulu nemusíme nutně používat metodu QueryInterface(), nebot většina komponent svými členskými metodami umožňuje zpřístupnit rozhraní k dalším COM serverům, které původní komponenta používá a již vytvořila jejich instanci. Na nejvyšší úrovni hierarchie komponent se nachází objekt DTE 4, který je základem pro všechny ostatní komponenty. Prvním krokem při vyvíjení add-inu je tedy získání ukazatele na objekt DTE, který umožní získat další ukazatele na téměř všechny komponenty, at už přímo, nebo postupně přes meziobjekty, což znázorňuje následující obrázek. Microsoft Visual Studio ve verzi 8.0 (2005) obsahuje mnoho nových rozhraní, které jsou vylepšením předchozích verzí. Názvy nových rozhraní, metod atd. mají většinou stejný název jako jejich starší verze, ale na konec je přidána dvojka (například DTE2), aby bylo možné používat původní verze pod shodným názvem. Doporučeno je ovšem použití novějších verzí, která mají vylepšené funkce a zaručují vyšší kompatibilitu se současnými operačními systémy. V této pu- 4 objekt DTE je umístěn ve jmenném prostoru (namespace) s názvem EnvDTE
27 KAPITOLA 3. ZÁSUVNÉ MODULY PRO MICROSOFT VISUAL STUDIO 15 blikaci jsou použity převážně názvy novějších verzí pro Microsoft Visual Studio 8.0 (2005), pokud není explicitně uvedeno, že se jedná o verzi pro Microsoft Visual Studio 7.1 (2003). 3.4 Vytváření zásuvného modulu Vytvořit zásuvný modul pomocí technologie COM obecně znamená implementovat metody rozhraní, které jsou speciálně vytvořeny pro tento účel. Microsoft Visual Studio nabízí pro zásuvné moduly rozhraní _IDTExtensibility2, jehož implementace zajišt uje základní životní funkce zásuvného modulu. Samotné rozhraní _IDTExtensibility2 by pro vytvoření užitečného addinu nestačilo, a proto je důležité implementovat další rozhraní s názvem IDTCommandTarget, které umožní provádět operace vyvolané akcí uživatele, například je možné reagovat na kliknutí na položku v menu podle jejího názvu. Samozřejmě je možné implementovat další rozhraní v závislosti na potřebách konkrétního vyvíjeného add-inu. Pro ulehčení práce při tvorbě zásuvného modulu (a obecně při tvorbě COM komponent) je výhodné použít tříd ATL knihovny, které implementují některé rutinní operace. Základem jsou třídy CComObjectRootEx a CComCoClass, které poskytují metody pro vytváření instancí třídy a počítání odkazů Průvodce pro vytváření kostry add-inu Pro vytvoření funkčního zásuvného modulu je nutné dodržet mnoho pravidel a příprava projektu před samotnou implementací jeho funkcí by byla ručně příliš zdlouhavá. Jednodušším řešením, které Microsoft Visual Studio nabízí, je vytvoření základního kódu automaticky pomocí průvodce, který vygeneruje projekt se všemi náležitostmi, které jsou potřeba pro přeložení a připojení add-inu. Autor zásuvného modulu si může kód upravit podle svých představ a následně přidávat vlastní kód, který bude vykonávat požadované operace. Průvodce pro vytvoření zásuvného modulu se spustí při vytváření nového projektu v Microsoft Visual Studiu a nastavení typu projektu na Visual Studio Add-in, který se nachází v kategorii Other Project Types/Extensibility. Obrázek 3.2: Spuštění průvodce pro vytvoření add-inu Kliknutím na tlačítko OK je spuštěn průvodce, který se postupně dotazuje na základní vlastnosti nově vytvářeného add-inu:
28 16 KAPITOLA 3. ZÁSUVNÉ MODULY PRO MICROSOFT VISUAL STUDIO 1. Nejprve se volí programovací jazyk, v kterém má být zásuvný modul vyvíjen C#, Visual Basic, J# nebo C++. V jazyce C++ je možné zvolit programování pro CLR (Common Language Runtime), což je virtuální počítač zpracovávající programy v jazyce MSIL (Microsoft Intermediate Language). CLR překladá MSIL kód do nativního kódu procesoru až za běhu aplikace a programátorovi poskytuje důležité služby pro správu paměti a vláken, obsluhu výjimek a zajištění bezpečnosti. Jedná se o již zmiňovaný řízený kód. Druhou možností vývoje v jazyce C++ je použití ATL knihovny, která programátorovi také nabízí mnoho služeb. Narozdíl od CLR je program přeložen rovnou do binárního (neřízeného) kódu proveditelného procesorem a add-in provádí užitečné operace rychleji. Volba závisí na požadavcích a zkušenostech programátora. Obrázek 3.3: Průvodce pro vytvoření add-inu - krok č V dalším kroku jsou na výběr klientské aplikace, pro které je zásuvný modul určen. Zde je podstatná první položka, což je Microsoft Visual Studio. Obrázek 3.4: Průvodce pro vytvoření add-inu - krok č. 2
29 KAPITOLA 3. ZÁSUVNÉ MODULY PRO MICROSOFT VISUAL STUDIO V následujícím okně průvodce lze nastavit název zásuvného modulu a krátký text stručně popisující jeho funkci. Ve správci add-inů bude tímto názvem a popiskem zásuvný modul reprezentován po jeho registraci. Obrázek 3.5: Průvodce pro vytvoření add-inu - krok č Další krok umožňuje nastavit tři přepínače. Zatrhnutí první volby způsobí vygenerování zdrojového kódu, který přidá položku do nabídky Tools, jejíž obsluhu je možné v zásuvném modulu implementovat. Druhá volba způsobí, že add-in bude ke klientské aplikaci připojován bezprostředně po jejím spuštění. Zatrhnutí poslední položky oznamuje, že add-in nikdy nebude vyžadovat reakci uživatele prostřednictvím grafického rozhraní, a že je možné ho použít s programy na příkazové řádce. Obrázek 3.6: Průvodce pro vytvoření add-inu - krok č V pátém kroku je možné nastavit, zda se má v okně About v nápovědě k Microsoft Visual Studiu zobrazovat informační text uvedený v textovém poli pod touto volbou.
30 18 KAPITOLA 3. ZÁSUVNÉ MODULY PRO MICROSOFT VISUAL STUDIO V posledním okně průvodce je zobrazeno shrnutí nastavených voleb a po stisknutí tlačítka Finish je vygenerována základní struktura zásuvného modulu, který lze již přeložit, zaregistrovat a připojit k Microsoft Visual Studiu. Je-li pro add-in zvolen programovací jazyk C++ s využitím knihovny ATL, průvodce vygeneruje soubory uvedené v tabulce 3.1. Název souboru AddIn.cpp AddIn.def AddIn.idl AddIn.rgs Connect.h Connect.cpp stdafx.h Popis obsahu Soubor obsahuje definici funkcí exportovaných výslednou DLL knihovnou, které poskytují základní služby pro práci s COM serverem registraci modulu v operačním systému (funkcí DllRegisterServer()), vytvoření instance komponenty (funkcí DllGetClassObject()) a další související funkce. Implementace všech funkcí s využitím metod ATL knihovny je vytvořena průvodcem. Deklarace exportovaných funkcí, které jsou definovány v AddIn.cpp. Zdrojový kód typové knihovny v jazyce IDL. Umístění a hodnoty klíčů vytvářených v registrech Windows při registraci add-inu. Deklarace hlavní třídy komponenty s názvem CConnect, která je odvozena děděním ze tříd knihovny ATL (CComObjectRootEx a CComCoClass) a z rozhraní IDTCommandTarget a _IDTExtensibility2. Připravená implementace třídy CConnect definice virtuálních funkcí rozhraní IDTCommandTarget a _IDTExtensibility2 s minimálním potřebným kódem pro přeložení. Autor add-inu doplní implementace metod v tomto souboru o vlastní kód vykonávající účelnou funkci zásuvného modulu. V souboru je definováno vložení hlavičkových souborů ATL knihovny a import použitých rozhraní. Tabulka 3.1: Popis projektových souborů add-inu Rozhraní _IDTExtensibility2 Metody rozhraní _IDTExtensibility2 implementované třídou komponenty vykonávají svůj kód jako reakci na událost, která ovlivňuje add-in. Microsoft Visual Studio volá tyto funkce když se modul připojí, odpojí, změní a podobně. Členské metody, které musí každý add-in implementovat jsou: OnAddInsUpdate() metoda je volána pokaždé když se add-in připojí nebo odpojí od integrovaného vývojové prostředí Microsoft Visual Studia OnBeginShutdown() metoda se provede před vypnutím Microsoft Visual Studia, pokud je zásuvný modul připojen během vypínání OnConnection() funkce se provede ihned po připojení add-inu a proto je vhodné v ní provést inicializaci, například získat rozhraní DTE2 voláním funkce QueryInterface() a jeho ukazatel uložit do členské proměnné, nebot jej jistě bude add-in dále využívat OnDisconnection() funkce se provede při odpojování add-inu a je tedy vhodné, aby prováděla případné úklidové operace OnStartupComplete() pokud je zásuvný modul nastaven na automatické spouštění při startu Microsoft Visual Studia, je při spuštění volána tato metoda
31 KAPITOLA 3. ZÁSUVNÉ MODULY PRO MICROSOFT VISUAL STUDIO Přidávání prvků do uživatelského rozhraní (IDTCommandTarget) Pokud má zásuvný modul provádět některé operace na požadavek uživatele, je nutné přidat příkaz, který bude moci uživatel spustit použitím prvku v uživatelském rozhraní. Pomocí rozhraní DTE2 je možné získat ukazatel na rozhraní Commands2, které umožňuje svou metodou AddNamedCommand2() přidat příkaz označený klíčovým názvem. Funkce AddNamedCommand2() jako parametr vyžaduje název příkazu, status a typ ovládacího prvku, a další informace. Návratový parametr je ukazatel na objekt typu Command, který lze pomocí volání metody AddControl() využít pro přidání ovládacího prvku do některého menu Microsoft Visual Studia. Příklad přidání příkazu a jeho ovládacího prvku je uveden v kapitole Implementace na straně 21. Aby mohl add-in reagovat na příkaz podle jeho názvu, musí implementovat rozhraní IDTCommandTarget, které obsahuje dvě virtuální metody QueryStatus() a Exec(). Metoda QueryStatus() je vývojovým prostředím volána vždy bezprostředně před zpřístupněním ovládacího prvku uživateli, například před rozbalením menu, ve kterém se ovládací prvek nachazí. HRESULT stdcall QueryStatus( BSTR CmdName, vscommandstatustextwanted NeededText, vscommandstatus* StatusOption, VARIANT* CommandText ); V jejím prvním parametru bstrcmdname je obsažen název příkazu, který je právě kontrolován. Druhý argument s názvem NeededText je konstanta určující typ požadované návratové informace. Třetí parametr StatusOption je návratový a jeho hodnota určuje status příkazu, zda je zapnutý, vypnutý, skrytý atd. Poslední parametr CommandText obsahuje ukazatel na textový řetězec vrácený funkcí, pokud byl argumentem NeededText vyžadován. Metodu Exec() Microsoft Visual Studio volá při spuštění příkazu. Porovnáním názvu příkazu, který je získán z parametru CmdName, lze zjistit, jaký požadavek má být zpracován. Implementace funkce Exec() je vlastně veškerý kód proveditelný všemi přidanými příkazy. HRESULT stdcall Exec( BSTR CmdName, vscommandexecoption ExecuteOption, VARIANT* VariantIn, VARIANT* VariantOut, VARIANT_BOOL* handled ); První parametr CmdName je název příkazu, který se má provést. Druhý parametr ExecuteOption určuje jak se má příkaz provést zda je možné se dotazovat uživatele na informace či nikoliv, nebo zda se má pouze zobrazit nápověda a příkaz se provádět nemá. Následující parametry VariantIn a VariantOut jsou ukazatele na datový typ VARIANT a umožňují předat libovolná data do funkce a z funkce. Poslední parametr handled je výstupní a měl by být nastaven na hodnotu true pokud je příkaz implementován a proveden, v opačném případě na false.
32 20 KAPITOLA 3. ZÁSUVNÉ MODULY PRO MICROSOFT VISUAL STUDIO Reakce na události (IDispEventImpl) Při vývoji zásuvného modulu je kromě provádění příkazů vyvolaných uživatelem často nutné také reagovat na vnitřní události vývojového prostředí. Knihovna ATL nabízí řešení pomocí šablony rozhraní IDispEventImpl<>, jejímž parametrem je identifikátor IID konkrétního rozhraní pracujího s údálostmi požadovaného typu, jehož metody budou implementovány v odvozené třídě. Například lze použít BuildEvents na obsluhu událostí souvisejících s překladem (začátek čí dokončení překladu), CommandEvents pro události volání příkazu z menu (před či po provedení libovolného příkazu), DocumentEvents na události editoru dokumentů (otevření, zavření či uložení dokumentu) a další. Ve třídě odvozené od IDispEventImpl<> je možné implementovat obsluhy událostí v metodách, jejichž názvy jsou přiřazeny ke konkrétním událostem pomocí makra SINK_ENTRY_EX. Před začátkem bloku maker mapujících jednotlivé metody na události, je nutné zadat makro BEGIN_SINK_MAP() s parametrem třídy, ve které jsou definovány mapované metody. Na závěr je blok ukončen makrem END_SINK_MAP(). Propojení zdroje událostí s třídou implementující jejich obsluhy se provádí funkcí ATL knihovny s názvem DispEventAdvise(), která jako argument vyžaduje ukazatel na rozhraní jehož implementace produkuje události. Rozhraní lze získat vhodnou metodou objektu Events (například get_buildevents(), get_commandevents(), get_documentevents()). Ukazatel na Events poskytuje objekt DTE2 metodou get_events(). Zrušení směrování událostí na nastavené metody obsluhy lze provést voláním funkce DispEventUnadvise(). 3.5 Registrace zásuvného modulu Dříve než je možné vytvořený zásuvný modul používat, je nutné jej zaregistrovat jako COM komponentu v operačním systému, což bylo již dříve popsáno v sekci Druhou možností, kterou nabízí Microsoft Visual Studio ve verzi 8.0 (2005), je do složky s DLL knihovnou přidat další soubor s příponou.addin, ve kterém jsou ve formátu XML popsány potřebné informace pro zobrazení zásuvného modulu ve správci add-inů. Microsoft Visual Studio při svém spuštění vyhledá soubory s příponou.addin v nastavené složce (výchozím nastavením je Visual Studio 2005\Addins ve složce Dokumenty ve Windows) a podle jejich obsahu přidá položky do správce add-inů, kde je možné zásuvné moduly aktivovat. Tento způsob umožňuje snadnou instalaci zásuvného modulu s řízeným kódem pouhým zkopírováním souborů s příponou.dll a.addin. V Microsoft Visual Studiu verze 7.1 (2003) je kromě registrace COM komponenty nutné vytvořit další záznam v registrech Windows, který je načítán správcem add-inů. Do registrů ke klíči HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.1\AddIns je potřeba přidat podklíč s názvem tvořeným názvem add-inu a tečkou odděleným názvem jeho hlavní třídy, tedy již zmiňovaný ProgID zásuvného modulu, například MujAddin.Connect. Hodnoty tohoto podklíče jsou pouze volitelné (není nutné je vytvářet), nicméně zpřehledňují zobrazení ve správci add-inů hodnota FriendlyName obsahuje název v čitelnější podobě, hodnota Description je text stručně popisující funkci zásuvného modulu a hodnota LoadBehavior je číselná konstanta určující zda se má add-in připojovat při startu vývojového prostředí (hodnota 1 znamená, že ano). V projektovém souboru AddIn.rgs jsou definovány všechny klíče a jejich hodnoty, které se mají vytvořit v registrech Windows při registraci add-inu metodou DllRegisterServer(). Úpravou tohoto souboru lze snadno měnit hodnoty ukládané do registrů, které vygeneroval průvodce při vytváření projektu, a případně přidávat další klíče pro vlastní potřeby zásuvného modulu.
33 KAPITOLA 4. IMPLEMENTACE 21 4 Implementace Součástí této bakalářské práce je zásuvný modul pro Microsoft Visual Studio. S využitím teorie programování COM komponent a zásuvných modulů pro Microsoft Visual Studio, která je popsána v přechozí kapitole, je vytvořen add-in s názvem Disassembler, jehož implementace bude dále vysvětlena. Na přiloženém CD je k dispozici kompletní zdrojový kód zásuvného modulu pro obě verze Microsoft Visual Studia, které podporuje 1. Dále je na CD instalátor, který podle verze Microsoft Visual Studia instalované v počítači zkopíruje správnou verzi DLL knihovny komponenty a provede další operace nutné pro její používání. 4.1 Microsoft Visual Studio 8.0 (2005) Add-in byl nejprve vyvíjen pro Microsoft Visual Studio verze 8.0 (2005) a poté byl duplikát hotového zdrojového kódu upraven pro verzi 7.1 (2003). Implementace bude popsána ve stejném pořadí jako byl zásuvný modul vyvíjen. Prvním krokem k vytvoření zásuvného modulu bylo použití průvodce s volbou programovaní v jazyce C++ s využitím knihovny ATL (viz. sekce 3.4.1). Průvodce vygeneroval kostru add-inu s deklarací třídy CConnect, jejíž metody je nutno definovat v připraveném souboru Connect.cpp. Základem při programování zásuvného modulu je schopnost používat již existující komponenty, které poskytují uživatelské rozhraní pro výběr souboru, pro spuštění vlastního převodu zdrojového kódu z jazyka C/C++ do assembleru ovládacím prvkem a pro zobrazení výstupu v okně textového editoru. Další komponenty jsou nutné pro zkompilování vybraného souboru a zjištění kdy byl překlad dokončen obsluhou vhodné události. Aby bylo možné volat metody těchto komponent, je nutné k nim nejprve získat rozhraní. V Microsoft Visual Studiu je ve většině případech možné získat ukazatel na rozhraní metodou nadřazené komponenty. V jazyce C++ se používají názvy metod začínající na get_ a následuje název požadovaného rozhraní. Základní komponenta, ze které lze postupně získat všechna rozhraní použitá v bakalářské práci, se nazývá DTE2. Seznam použitých komponent a jejich hierarchie je znázorněna na obrázku 4.1. Například pro získání rozhraní pro práci s komponentou SolutionBuild je nutné nejprve obržet ukazatel na rozhraní Solution od objektu DTE2, což ukazuje následující fragment zdrojového kódu (proměnná m_pdte je chytrý ukazatel na rozhraní DTE2): CComQIPtr<_Solution> psolution; CComQIPtr<SolutionBuild> psolutionbuild; m_pdte->get_solution(&psolution); psolution->get_solutionbuild(&psolutionbuild); psolutionbuild->build(true); První dva řádky zdrojového kódu deklarují ukazatele na rozhraní Solution a SolutionBuild pomocí šablony třídy chytrého ukazatele na rozhraní s názvem CComQIPtr<>, který je součástí knihovny ATL. Následně je postupně získáno rozhraní SolutionBuild, které je na posledním řádku použito k přeložení projektových souborů metodou Build(). 1 kompatibilita s novějšími verzemi Microsoft Visual Studia je možná, nicméně funkčnost je ověřena jen pro verze 7.1 (2003) a 8.0 (2005)
34 22 KAPITOLA 4. IMPLEMENTACE Obrázek 4.1: Komponenty využívané zásuvným modulem Disassembler Inicializace zásuvného modulu (metoda CConnect::OnConnection()) Metoda OnConnection() je prováděna při připojení add-inu k Microsoft Visual Studiu a je vhodné aby inicializovala objekty, které bude zásuvný modul dále používat. Prototyp funkce OnConnection vypadá takto: virtual HRESULT stdcall OnConnection(IDispatch * papplication, ext_connectmode ConnectMode, IDispatch *paddininst, SAFEARRAY **custom); První parametr papplication je ukazatel na rozhraní IDispatch, který reprezentuje základní aplikaci Microsoft Visual Studia. Další argument ConnectMode oznamuje, jak byl add-in připojen zda automaticky po spuštění vývojového prostředí, externím programem, nebo komponentou, otevřením projektu, který jej vyžaduje, nebo jiným způsobem. Třetí parametr paddininst je ukazatel na rozhraní IDispatch reprezentující konkrétní instanci právě připojeného zásuvného modulu. Poslední parametr může obsahovat ukazatel na pole objektů typu VARIANT předávající libovolná data do funkce add-in Disassembler jej nevyužívá. Pro práci s existujícími komponentami Microsoft Visual Studia je potřeba získat zmiňovaný ukazatel na rozhraní DTE2, což je řešeno metodou QueryInterface() z objektu papplication. Jako vstupní parametr QueryInterface() je místo přímého zadání identifikátoru rozhraní GUID použit operátor uuidof(), který zjistí a vrátí GUID na základě jeho zadaného názvu. Podobně je získáno i rozhraní AddIn z objektu paddininst. papplication->queryinterface( uuidof(dte2), (LPVOID*)&m_pDTE); paddininst->queryinterface( uuidof(addin), (LPVOID*)&m_pAddInInstance);
35 KAPITOLA 4. IMPLEMENTACE 23 Následuje volání metody SetSink() třídy CBuildEvents, které nastaví obsluhy událostí překladu na metody definované v třídě CBuildEvents. Podrobněji je tato třída popsána v sekci Další kód slouží k přidání ovládacího prvku tlačítka Disassemble do kontextové nabídky v okně Solution Explorer. Příkaz vykonávaný po stisknutí tlačítka je vytvořen metodou AddNamedCommand2(), kterou implementuje rozhraní Commands2. pcommands2->addnamedcommand2(m_paddininstance, CComBSTR("Disassemble"), CComBSTR("Disassemble"), CComBSTR("Disassembles a C++ source code."), VARIANT_TRUE, CComVariant(0), NULL, vscommandstatussupported, vscommandstyletext, vscommandcontroltypebutton, &ppopupcommand); Prvním parametrem metody AddNamedCommand2, proměnnou m_paddininstance, je předán ukazatel na rozhraní IDispatch aktuální instance add-inu. Další tři argumenty jsou textové řetězce typu CComBSTR název identifikující příkaz, popisek ovládacího prvku (tlačítka) a stručný popisný text, který bude zobrazen při najetí kurzoru myši nad tlačítko. Následující parametr je typu bool a určuje, zda případný obrázek na tlačítku bude typu Office. Hodnota je zde nepodstatná, nebot v následujícím parametru je identifikátor obrázku nastaven na 0, tj. nebude se zobrazovat žádný obrázek. Sedmý parametr určuje v jakém kontextu má být příkaz přístupný (například může být přístupný pouze v ladícím, nebo v návrhovém módu) hodnota NULL znamená, že jeho přístupnost není omezena. Následující tři argumenty nastavují zobrazení ovládacího prvku příkazu vscommandstatussupported umožní měnit stav tlačítka před jeho zobrazením (viz. následující sekce 4.1.2), vscommandstyletext udává, že tlačítko bude označeno pouze textem a vscommandcontroltypebutton říká, že ovládací prvek má být tlačítko. Poslední parametr ppopupcommand je výstupní a při úspěšném provedení funkce v něm je obsažen ukazatel typu Command na právě přidaný příkaz. Nyní je potřeba umístit ovládací prvek vytvořeného příkazu do požadované nabídky. Nejprve je metodou get_commandbars() získano rozhraní CommandBars pro práci s příkazovými nabídkami, jehož metoda get_item() vrací ukazatel na rozhraní CommandBar konkrétní nabídky podle názvu. Disassembler používá nabídku označenou názvem Item, což představuje kontextovou nabídku souborů v okně Solution Exploreru. Přidání příkazu do této nabídky provede metoda AddControl() rozhraní Command: pcommandbars->get_item(ccomvariant(l"item"), &pitemcommandbar); ppopupcommand->addcontrol(pitemcommandbar, 1, &pdispatch); Prvním parametrem metody AddControl() je ukazatel na rozhraní nabídky Item, do které se má příkaz ppopupcommand přidat. Druhý parametr je číslo udávající pořadí tlačítka v nabídce. Nastavená hodnota 1 způsobí přidání ovládacího prvku úplně nahoru. Posledním parametrem pdispatch je vrácen ukazatel na rozhraní CommandBarControl, který dále není zapotřebí. Posledním krokem inicializace je získat handle hlavního okna aplikace Microsoft Visual Studio, což je nutný parametr funkce MessageBox(), která je použita pro zobrazení informačních oken za běhu add-inu. Handle okna, obdržený metodou komponenty MainWindow, je typu HWND a je uložen do třídní proměnné hwndmain Nastavení stavu ovládacího prvku (metoda CConnect::QueryStatus()) Před každým zobrazením přidaného tlačítka v rozbalovací nabídce je vývojovým prostředím volána metoda zásuvného modulu s názvem QueryStatus(). Její vhodná implementace u- možňuje měnit stav tlačítka před jeho zobrazením. Zásuvný modul Disassembler pomocí této metody zapíná nebo vypíná zobrazení tlačítka na základě přípony souboru, na kterém je kontextová nabídka vyvolána.
36 24 KAPITOLA 4. IMPLEMENTACE Nejprve metoda QueryStatus() porovná funkcí _wcsicmp() název příkazu, který má být zpracován. Hodnota předaná ve vstupním parametru bstrcmdname obsahuje název příkazu ve tvaru Program.Komponenta.Příkaz. Pokud je hodnota bstrcmdname nastavena na textový řetězec Disassembler.Connect.Disassemble, tj. je zjišt ován stav tlačítka, které bylo přidáno při inicializaci, provede se pomocí komponenty SelectedItems zjištění názvu označeného souboru. Jestliže název souboru končí příponou C nebo CPP, je vrácen stav vscommandstatussupported + vscommandstatusenabled a tlačítko Disassemble je v nabídce zobrazeno a je možné na něj kliknout. Pro ostatní soubory je vrácen stav vscommandstatusinvisible, což znamená, že je tlačítko skryto Provedení příkazu (metoda CConnect::Exec()) Když uživatel vývojového prostředí klikne na tlačítko Disassemble, Microsoft Visual Studio volá metodu zásuvného modulu s názvem Exec(), která má provést obsluhu příkazu. V prvním argumentu je metodě předán název příkazu, který se má provést, a podobně jako u metody QueryStatus() je tato hodnota testována a v případě, že odpovídá názvu tlačítka Disassemble, jsou provedeny následující akce. Nejprve je pomocí rozhraní SelectedItems získána vybraná položka v podobě ukazatele na typ SelectedItem, která poskytuje rozhraní ProjectItem, pomocí kterého je zjištěna absolutní cesta ke zdrojovému souboru. Z cesty k C nebo CPP souboru je odvozen název objektového souboru nahrazením původní přípony za OBJ a odříznutím části textového řetězce před zpětným lomítkem. Obdržený řetězec je uložen do proměnné objfile a může mít hodnotu například zdrojovy_soubor.obj. Microsoft Visual Studio ukládá objektové soubory do podsložky projektu, která má název podle zvolené konfigurace překladu (například předdefinované konfigurace Debug a Release). Pro zjištění absolutní cesty k objektovému souboru, který vznikne při překladu, je tedy nutné znát ještě název konfigurace. Nejdříve je metodou get_activesolutionprojects() získáno pole typu SafeArray obsahující aktivní projekty otevřené ve vývojovém prostředí. Funkcí SafeArrayGetLBound() je zjištěn index prvního prvku, který je pak předán funkci SafeArrayGetElement() a ta vrátí objekt typu VARIANT, který již obsahuje ukazatel na rozhraní Project představující otevřený projekt uživatele add-inu. Rozhraní Project umožňuje získat rozhraní ConfigurationManager a z něj pak rozhraní ActiveConfiguration, které je použito pro zjištění názvu konfigurace, kterou má uživatel zásuvného modulu právě zvolenu. Výslednou absolutní cestu k objektovému souboru tvoří cesta ke složce projektu zjištěná z cesty ke zdrojovému souboru, následuje složka s názvem aktivní konfigurace a nakonec název souboru z proměnné objfile. Cesta k objektovému souboru je uložena do globální proměnné OBJFile. Pokud objektový soubor již existuje z předchozího překladu, je smazán, aby bylo zaručeno, že je vždy zpracováván aktuální objektový soubor odpovídající přeloženému zdrojovému kódu. Dále je nastavena textová proměnná asmfile na hodnotu absolutní cesty k vytvářenému souboru se symbolickými instrukcemi, která se liší od cesty k objektovému souboru pouze příponou změněnou na ASM. Následně je vygenerován textový řetězec obsahující spouštěcí parametry k programu dumpbin, který je zapsán do proměnné params. Před spuštěním překladu zásuvný modul ještě zjistí, zda není soubor se symbolickými instrukcemi již otevřen z předchozího použití add-inu. Pokud by byl otevřen a byl by změněn programem dumpbin, vývojové prostředí by hlásilo, že ho upravila externí aplikace, a bylo by nutné klikat na dialogové okno. Add-in metodou objektu DTE2 s názvem get_isopenfile() zjistí, jestli soubor s názvem v proměnné asmfile je otevřen. Pokud ano, je metodou OpenFile() získáno rozhraní Window, které umožní soubor zavřít metodou Close(). Posledním krokem, který je možné v metodě Exec() provést, je spuštění překladu. To je provedeno použitím komponenty SolutionBuild, která metodou Build() přeloží projekt
37 KAPITOLA 4. IMPLEMENTACE 25 s použitím aktivní konfigurace a vznikne potřebný objektový soubor. Rozhraní SolutionBuild je získáno z objektu DTE2 přes rozhraní Solution: m_pdte->get_solution(&psolution); psolution->get_solutionbuild(&psolutionbuild); disassembling = TRUE; psolutionbuild->build(disassembling); Z uvedené části zdrojového kódu je vidět nastavení disassembling na hodnotu TRUE. Proměnná disassembling je globální a určuje, že právě prováděný překlad je pro účel tohoto zásuvného modulu. Parametr metody Build() neplní svůj význam uváděný Microsoftem a proto jeho hodnota může být libovolná. Další operace pro převedení zdrojového kódu do assembleru je nutno provádět až po dokončení překladu, tj. po vytvoření objektového souboru Třída CBuildEvents obsluhující překladové události Za účelem detekce dokončení překladu je vytvořena třída CBuildEvents, která je odvozena děděním od šablony rozhraní IDispEventImpl<>. Důležitým parametrem IDispEventImpl<> je GUID identifikující rozhraní, přes které vývojové prostředí přistupuje k metodám implementovaným ve třídě CBuildEvents, pokud jsou mapovány k některé události zvoleného rozhraní. Pro zachycení události konce překladu je jako parametr šablony použito rozhraní _dispbuildevents. Ve třídě CBuildEvents jsou definovány (kromě konstruktoru a destruktoru) tři metody SetSink(), RemoveSink a OnBuildDone(). Funkce SetSink() je volána při inicializaci v metodě CConnect::OnConnection() a jako argument je do ní předán ukazatel na rozhraní DTE2. Od DTE2 je získáno rozhraní Events, které poskytuje rozhraní BuildEvents. Na závěr je volána funkce DispEventAdvise(), která nastaví obsluhu událostí produkovaných rozhraním BuildEvents na metody definované v třídě CBuildEvents: m_pdte->get_events(&pevents); pevents->get_buildevents((envdte::_buildevents**)&m_pbuildevents); DispEventAdvise((IUnknown*)m_pBuildEvents.p); Metoda RemoveSink() slouží k odpojení zdroje událostí od jejich obsluhy definované třídou CBuildEvents a je volána při odpojování add-inu v těle metody CConnect::OnDisconnection(). Odpojení provádí pomocí funkce DispEventUnadvise() s parametrem m_pbuildevents, což je třídní proměnná nastavená ve funkci SetSink(). Poslední metoda OnBuildDone() představuje obsluhu události dokončení překladu. Mapovaní události na tuto metodu je provedeno následujícími makry: BEGIN_SINK_MAP(CBuildEvents) SINK_ENTRY_EX(1, uuidof(envdte::_dispbuildevents), 4, OnBuildDone) END_SINK_MAP() Makro SINK_ENTRY_EX nastavuje jako obsluhu události reprezentované metodou rozhraní _dispbuildevents s identifikátorem DISPID = 4 (zadáno v druhém a třetím parametru) funkci s názvem OnBuildDone (zadáno v posledním parametru) Obsluha dokončení překladu (metoda CBuildEvents::OnBuildDone()) Po dokončení překladu projektu ve vývojovém prostředí je za běhu add-inu vždy provedena funkce OnBuildDone(). Je nutné ještě rozlišit, zda byl překlad spuštěn add-inem za
38 26 KAPITOLA 4. IMPLEMENTACE účelem převodu zdrojového kódu do assembleru, nebo zda byl spuštěn jiným způsobem (například uživatel add-inu pouze přeložil vyvíjený projekt příkazem v nabídce). Proto metoda OnBuildDone() nejdříve testuje hodnotu proměnné disassembling, která je před spuštěním překladu v metodě Exec() nastavena na TRUE. Další kód funkce se provede pouze pokud je hodnota TRUE, v opačném případě metoda OnBuildDone() končí. Následuje test existence objektového souboru s názvem v proměnné OBJFile, jehož nenalezení znamená chybu a taktéž ukončení metody. Pokud objektový soubor existuje, provádí se spuštění dávky disasm.bat, která volá program dumpbin. K tomu je nutné nejprve nastavit parametry ve struktuře SHELLEXECUTEINFO, která obsahuje veškeré informace pro provedení externího programu funkcí ShellExecuteEx(): SHELLEXECUTEINFO exec; ZeroMemory(&exec, sizeof(shellexecuteinfo)); exec.cbsize = sizeof(shellexecuteinfo); exec.fmask = SEE_MASK_NOCLOSEPROCESS; exec.hwnd = hwndmain; exec.lpfile = _T("disasm.bat"); exec.lpparameters = params; exec.lpdirectory = get_disasmdir(); exec.nshow = SW_HIDE; ShellExecuteEx(&exec); DWORD exitcode; GetExitCodeProcess(exec.hProcess, &exitcode); int cykly = 0; while (exitcode == STILL_ACTIVE) { if (++cykly > 50) { MessageBox(hWndMain, _T("Timeout!"), _T("Disassembler error"), MB_OK MB_ICONERROR); break; } Sleep(200); GetExitCodeProcess(exec.hProcess, &exitcode); } Nejprve je struktura SHELLEXECUTEINFO vymazána metodou ZeroMemory() a následně jsou nastaveny jednotlivé atributy pro spouštění (vynechaným atributům zůstane hodnota 0, což označuje jejich výchozí nastavení například lpverb specifikující požadovanou operaci se souborem má výchozí hodnotu open a bude se tedy provádět otevření (spuštění) souboru): cbsize velikost struktury v bytech fmask obsah a platnost atributů struktury nastavená kombinací konstant hodnota SEE_MASK_NOCLOSEPROCESS určuje, že atribut hproces bude nastaven na handle procesu, ve kterém bude program spuštěn hwnd handle okna aplikace, ve kterém budou zobrazena případná informační okna lpfile ukazatel na textový řetězec obsahující název souboru, který se má spustit lpparameters ukazatel na textový řetězec obsahující parametry, které se předají spouštěnému programu (jednotlivé parametry musí být v textu odděleny mezerou stejně jako při spouštění aplikace v systémové konzoli)
39 KAPITOLA 4. IMPLEMENTACE 27 lpdirectory ukazatel na textový řetězec obsahující název složky, ze které je volán spouštěný program nshow způsob zobrazení spouštěné aplikace Po zavolání metody ShellExecuteEx() se cyklicky zjišt uje stav procesu, ve kterém je prováděn program dumpbin funkcí GetExitCodeProcess() je vrácena hodnota označující stav procesu identifikovaného jeho handlem v proměnné exec.hprocess a pokud proces stalé probíhá (tj. hodnota odpovídá konstantě STILL_ACTIVE), add-in je funkcí Sleep() na 200 milisekund pozastaven a poté se cyklus opakuje dokud proces neskončí. V případě, že by volaný program běžel déle než 10 vteřin (což odpovídá vykonání padesáti iterací cyklu), je cyklus ukončen a zobrazeno varovné okno. Toto opatření zajišt uje, aby nedošlo k zacyklení add-inu v případě, že externě volaný program z jakéhokoliv důvodu zamrzne. Pokud proces skončí bezchybně a je opuštěn čekací cyklus, tj. předpokládá se, že soubor se zdrojovým kódem v assembleru je již vytvořen, je možné zobrazit výsledek v okně textového editoru Microsoft Visual Studia. Otevření je provedeno metodou objektu DTE2 s názvem OpenFile(), které je předán název souboru v proměnné asmfile. Po otevření okna zobrazujícího obsah souboru se symbolickými instrukcemi je metodou Activate() zajištěno jeho zobrazení na popředí. 4.2 Microsoft Visual Studio 7.1 (2003) Implementace verze add-inu pro Microsoft Visual Studio 7.1 (2003) je principiálně stejná jako pro verzi 8.0 (2005), rozdíl je především v nahrazení tříd jmenného prostoru EnvDTE2, který ve starší verzi ještě neexistuje. Použity jsou obdobné komponenty definované ve jmenném prostoru EnvDTE. Konkrétně místo DTE2 je použit DTE, spouštěcí příkaz je přidán pomocí komponenty Commands (místo novější verze Commands2) metodou AddNamedCommand() (místo AddNamedCommand2()). Z důvodu starší verze je navíc potřeba při odpojování zásuvného modulu (v metodě CConnect::OnDisconnection()) odebírat přidaný příkaz a jeho ovládací prvek, což je řešeno metodou Delete() rozhraní CommandBar, které je získáno z rozhraní CommandBars funkcí get_item() na základě názvu příkazu. Pokud by nebyl prvek odebírán, při dalších připojeních add-inu by se do kontextového menu přidávaly další shodné položky při přidávání novější metodou AddNamedCommand2() duplikace nevznikají. 4.3 NSIS instalátor Vytvoření instalátoru NSIS spočívá v napsání skriptu ve speciálním jazyce navrženém firmou Nullsoft, který je zpracován překladačem a vzniká spustitelný EXE soubor. Nejprve jsou v instalačním skriptu zvoleny hlavičkové soubory umožňující použití předdefinovaných funkcí, konkrétně je použit soubor WordFunc.nsh, který poskytuje potřebnou funkci WordReplace. Následně je definován název aplikace (klíčovým slovem Name), název výstupního spustitelného souboru (OutFile), výchozí cílová složka pro instalaci (InstallDir) a umístění klíče v registrech Windows, ve kterém bude zapsána cílová složka pro případ přeinstalování, aby byla přepsána původní instalace ve stejné složce (InstallDirRegKey). Další část skriptu klíčovým slovem Page nastavuje, že se mají zobrazit při instalaci stránky pro výběr instalovaných součástí, pro změnu cílové složky a nakonec stránka s průběhem instalace. Dále jsou v blocích mezi slovy Section a SectionEnd uzavřeny jednotlivé součásti instalace první dvě sekce odpovídají instalaci add-inu pro verzi Microsoft Visual Studia 8.0 (2005) a 7.1 (2003), třetí s názvem Uninstall obsahuje kód pro odinstalovaní zásuvného modulu, který se provede spuštěním vygenerovaného souboru uninstall.exe.
40 28 KAPITOLA 4. IMPLEMENTACE V první sekci se provádí instalace modulu pro verzi 8.0 (2003) neprve se z registrů Windows načte složka, ve které je nainstalované Microsoft Visual Studio, a poté je náhradou části řetězce získána složka umístění programu dumpbin. Pak je nastavena cílová složka pro instalaci příkazem SetOutPath, zkopírován DLL soubor s add-inem použitím klíčového slova File a knihovna je zaregistrována v operačním systému voláním příkazu RegDLL. Dále je vytvořen dávkový soubor obsahující nastavení systémové proměnné PATH přidáním složky, kde je umístěn dumpbin, nebot v ní budou nalezeny další soubory, které dumpbin vyžaduje pro svůj běh. Následně je v dávce vlastní volání programu dumpbin s předáním parametrů, které jsou dávce předávány add-inem při jejím spouštění. V poslední části sekce jsou do registrů zapsány informace pro odinstalování, které Windows využívají při odstraňování aplikace přes Ovládací panely, a je zapsán spustitelný soubor provádějící odinstalaci příkazem WriteUninstaller. Další sekce funguje analogicky stejně pro verzi 7.1 (2003), pouze se liší názvy klíčů čtených z registrů a názvy DLL knihovny a dávkového souboru. Narozdíl od verze 8.0 se v této sekci navíc zapíšou informace o zásuvném modulu do registrů Windows, nebot je vyžaduje správce add-inů ve starší verzi Microsoft Visual Studia. Poslední sekce s názvem Uninstall provede odstranění add-inu z počítače. Zrušení registrace DLL knihovny se provede příkazem UnRegDLL, dále jsou smazány záznamy v registrech vytvořené při instalaci a všechny soubory v instalační složce. Na konci skriptu je definována funkce se speciálním názvem.oninit, která je volána bezprostředně po spuštění instalátoru. Funkce čte z registrů Windows záznamy o instalaci obou podporovaných verzí Microsoft Visual Studia. Pokud je záznam nalezen (tj. daná verze Microsoft Visual Studia je v počítači nainstalována), je zatrhnuta položka na stránce výběru součástí. Pokud klíč v registrech nalezen není, součást není vybrána a je zamezeno uživateli, aby ji mohl zatrhnout. Stav položek na stránce výběru součástí lze měnit nastavením příznaků pomocí volání SectionSetFlags.
41 KAPITOLA 5. ZÁVĚR 29 5 Závěr Vytvořený zásuvný modul pro převod zdrojových kódů z jazyka C/C++ do assembleru může být užitečným pomocníkem vývojářů programujících v prostředí Microsoft Visual Studio. Díky instalátoru je možné velmi snadno add-in připravit k použití, aniž by uživatel musel znát principy, na kterých funguje. Dalším přínosem této bakalářské práce je shrnutí informací o tvorbě zásuvných modulů do Microsoft Visual Studia a obecně programování komponentových aplikací postavených na architektuře COM. Teorie je lépe pochopitelná díky detailnímu popisu implementace add-inu, který provádí operace často potřebné i u zásuvných modulů s úplně jiným významem (například přidávání ovládacích prvků do nabídek a jejich obsluha, reakce na různé typy událostí a podobně). Vše je vysvětleno velmi do hloubky, nebot materiálů k této problematice existuje velmi málo, především pak v českém jazyce. Zásuvný modul byl testován na několika různých počítačích a pro obě podporované verze Microsoft Visual Studia fungoval správně podle předem vymezených požadavků. Nicméně addin by bylo možné dále rozšířit o podporu převodu do assembleru z dalších programovacích jazyků použitelných při vývoji v Microsoft Visual Studiu komponentový model by zůstal stejný, pouze by bylo nutné přidat použití dalších programů pro generování kódu v jazyce symbolických instrukcí a individuálně řešit náležitosti související s jednotlivými programovacími jazyky. Obrázek 5.1: Ukázka použití zásuvného modulu Disassembler
42 30 KAPITOLA 6. LITERATURA 6 Literatura [1] R. Chalupa. Programování COM objektů, ActiveX a Win32 aplikací. BEN, [2] Eternal s.r.o. Progres, [3] Microsoft. Microsoft Developer Network, [4] Nullsoft. Nullsoft Scriptable Install System, [5] D. Rogerson. Inside COM. Microsoft Press, [6] sourceware.org. GNU Binary Utilities, [7] Wikipedia Foundation. Wikipedia encyklopedia,
43 KAPITOLA 6. LITERATURA 31
44 32 KAPITOLA 6. LITERATURA
45 DODATEK A. HIERARCHIE KOMPONENT MICROSOFT VISUAL STUDIA 33 A Hierarchie komponent Microsoft Visual Studia Obrázek A.1: Hierarchie komponent Microsoft Visual Studia
TÉMATICKÝ OKRUH Softwarové inženýrství
TÉMATICKÝ OKRUH Softwarové inženýrství Číslo otázky : 25. Otázka : Komponentní technologie - základní pojmy a principy, metody specifikace komponent. Obsah : 1. Základní pojmy 1.1 Komponenta Komponenta
Bridge. Známý jako. Účel. Použitelnost. Handle/Body
Bridge Bridge Známý jako Handle/Body Účel odděluje abstrakci (rozhraní a jeho sémantiku) od její konkrétní implementace předchází zbytečnému nárůstu počtu tříd při přidávání implementací používá se v době
MATURITNÍ OTÁZKY ELEKTROTECHNIKA - POČÍTAČOVÉ SYSTÉMY 2003/2004 PROGRAMOVÉ VYBAVENÍ POČÍTAČŮ
MATURITNÍ OTÁZKY ELEKTROTECHNIKA - POČÍTAČOVÉ SYSTÉMY 2003/2004 PROGRAMOVÉ VYBAVENÍ POČÍTAČŮ 1) PROGRAM, ZDROJOVÝ KÓD, PŘEKLAD PROGRAMU 3 2) HISTORIE TVORBY PROGRAMŮ 3 3) SYNTAXE A SÉMANTIKA 3 4) SPECIFIKACE
Sdílení dokumentů ve stávajícím informačním systému
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
ČÁST 1. Základy 32bitového programování ve Windows
Obsah Úvod 13 ČÁST 1 Základy 32bitového programování ve Windows Kapitola 1 Nástroje pro programování ve Windows 19 První program v Assembleru a jeho kompilace 19 Objektové soubory 23 Direktiva INVOKE 25
Obsah. Předmluva 13 Zpětná vazba od čtenářů 14 Zdrojové kódy ke knize 15 Errata 15
Předmluva 13 Zpětná vazba od čtenářů 14 Zdrojové kódy ke knize 15 Errata 15 KAPITOLA 1 Úvod do programo vání v jazyce C++ 17 Základní pojmy 17 Proměnné a konstanty 18 Typy příkazů 18 IDE integrované vývojové
Generické programování
Generické programování Od C# verze 2.0 = vytváření kódu s obecným datovým typem Příklad generická metoda, zamění dva parametry: static void Swap(ref T p1, ref T p2) T temp; temp = p1; p1 = p2; p2 =
Platforma.NET 11.NET Framework 11 Visual Basic.NET Základní principy a syntaxe 13
Obsah Úvod 11 Platforma.NET 11.NET Framework 11 Visual Basic.NET 12 1 Základní principy a syntaxe 13 Typový systém 13 Hodnotové typy 13 Struktury 15 Výčtové typy 15 Referenční typy 15 Konstanty 16 Deklarace
Úvod. Programovací paradigmata
.. Úvod. Programovací paradigmata Programovací techniky doc. Ing. Jiří Rybička, Dr. ústav informatiky PEF MENDELU v Brně rybicka@mendelu.cz Cíl: programování efektivně a bezpečně Programovací techniky
2015 GEOVAP, spol. s r. o. Všechna práva vyhrazena.
2015 GEOVAP, spol. s r. o. Všechna práva vyhrazena. GEOVAP, spol. s r. o. Čechovo nábřeží 1790 530 03 Pardubice Česká republika +420 466 024 618 http://www.geovap.cz V dokumentu použité názvy programových
typová konverze typová inference
Seminář Java Programování v Javě II Radek Kočí Fakulta informačních technologií VUT Únor 2008 Radek Kočí Seminář Java Programování v Javě (2) 1/ 36 Téma přednášky Rozhraní: použití, dědičnost Hierarchie
8 Třídy, objekty, metody, předávání argumentů metod
8 Třídy, objekty, metody, předávání argumentů metod Studijní cíl Tento studijní blok má za cíl pokračovat v základních prvcích jazyka Java. Konkrétně bude věnována pozornost třídám a objektům, instančním
1. Programování proti rozhraní
1. Programování proti rozhraní Cíl látky Cílem tohoto bloku je seznámení se s jednou z nejdůležitější programátorskou technikou v objektově orientovaném programování. Tou technikou je využívaní rozhraní
Architektura COM. Historie Component Object Model (COM) Komunikace s komponentami Rozhraní komponent COM komponenty v.net.
Architektura COM doc. Ing. Miroslav Beneš, Ph.D. katedra informatiky FEI VŠB-TUO A-1007 / 597 324 213 http://www.cs.vsb.cz/benes Miroslav.Benes@vsb.cz Obsah přednášky Historie Component Object Model (COM)
Komponenty v.net. Obsah přednášky
doc. Ing. Miroslav Beneš, Ph.D. katedra informatiky FEI VŠB-TUO A-1007 / 597 324 213 http://www.cs.vsb.cz/benes Miroslav.Benes@vsb.cz Obsah přednášky Rozdíl mezi COM a.net Distribuce komponent Programování
2) Napište algoritmus pro vložení položky na konec dvousměrného seznamu. 3) Napište algoritmus pro vyhledání položky v binárním stromu.
Informatika 10. 9. 2013 Jméno a příjmení Rodné číslo 1) Napište algoritmus pro rychlé třídění (quicksort). 2) Napište algoritmus pro vložení položky na konec dvousměrného seznamu. 3) Napište algoritmus
Úvod Seznámení s předmětem Co je.net Vlastnosti.NET Konec. Programování v C# Úvodní slovo 1 / 25
Programování v C# Úvodní slovo 1 / 25 Obsah přednášky Seznámení s předmětem Co je.net Vlastnosti.NET 2 / 25 Kdo je kdo Petr Vaněček vanecek@pf.jcu.cz J 502 Václav Novák vacnovak@pf.jcu.cz?? Při komunikaci
Seznámení s prostředím dot.net Framework
Základy programování v jazyce C# Seznámení s prostředím dot.net Framework PL-Prostředí dot.net - NET Framework Je základním stavebním prvkem, na kterém lze vytvářet software. Jeho součásti a jádro je založené
Programování v jazyce C a C++
Programování v jazyce C a C++ Richter 1 Petyovský 2 1. března 2015 1 Ing. Richter Miloslav, Ph.D., UAMT FEKT VUT Brno 2 Ing. Petyovský Petr, UAMT FEKT VUT Brno C++ Stručná charakteristika Nesdíĺı normu
Dědění, polymorfismus
Programování v jazyce C/C++ Ladislav Vagner úprava Pavel Strnad Dědění. Polymorfismus. Dnešní přednáška Statická a dynamická vazba. Vnitřní reprezentace. VMT tabulka virtuálních metod. Časté chyby. Minulá
Objektové programování
Objektové programování - přináší nové možnosti a styl programování - vytváří nový datový typ, který umí vše co standardní datové typy + to co ho naučíme - překladač se k tomuto typu chová stejně jako k
2015 GEOVAP, spol. s r. o. Všechna práva vyhrazena.
2015 GEOVAP, spol. s r. o. Všechna práva vyhrazena. GEOVAP, spol. s r. o. Čechovo nábřeží 1790 530 03 Pardubice Česká republika +420 466 024 618 http://www.geovap.cz V dokumentu použité názvy programových
Technologické postupy práce s aktovkou IS MPP
Technologické postupy práce s aktovkou IS MPP Modul plánování a přezkoumávání, verze 1.20 vypracovala společnost ASD Software, s.r.o. dokument ze dne 27. 3. 2013, verze 1.01 Technologické postupy práce
Dynamicky vázané metody. Pozdní vazba, virtuální metody
Dynamicky vázané metody Pozdní vazba, virtuální metody Motivace... class TBod protected: float x,y; public: int vrat_pocet_bodu() return 1; ; od třídy TBod odvodíme: class TUsecka: public TBod protected:
Úvod do programovacích jazyků (Java)
Úvod do programovacích jazyků (Java) Michal Krátký Katedra informatiky VŠB Technická univerzita Ostrava Úvod do programovacích jazyků (Java), 2007/2008 c 2006 2008 Michal Krátký Úvod do programovacích
Postupy práce se šablonami IS MPP
Postupy práce se šablonami IS MPP Modul plánování a přezkoumávání, verze 1.20 vypracovala společnost ASD Software, s.r.o. dokument ze dne 27. 3. 2013, verze 1.01 Postupy práce se šablonami IS MPP Modul
přetížení operátorů (o)
přetížení operátorů (o) - pro vlastní typy je možné přetížit i operátory (tj. definovat vlastní) - pro definici slouží klíčové slovo operator následované typem/znakem operátoru - deklarace pomocí funkčního
PŘETĚŽOVÁNÍ OPERÁTORŮ
PŘETĚŽOVÁNÍ OPERÁTORŮ Jazyk C# podobně jako jazyk C++ umožňuje přetěžovat operátory, tj. rozšířit definice některých standardních operátorů na uživatelem definované typy (třídy a struktury). Stejně jako
MS Excel makra a VBA
Autor: RNDr. Obsah: MS Excel makra a VBA 1 Využití, ukázky, výhody a nevýhody... 2 2 Makra a zabezpečení... 2 2.1 Nastavení zabezpečení Excelu... 2 2.2 Uložení maker do sešitu a osobního sešitu maker...
MIKROPROCESORY PRO VÝKONOVÉ SYSTÉMY
MIKROPROCESORY PRO VÝKONOVÉ SYSTÉMY Stručný úvod do programování v jazyce C 1.díl České vysoké učení technické Fakulta elektrotechnická A1B14MIS Mikroprocesory pro výkonové systémy 06 Ver.1.10 J. Zděnek,
TÉMATICKÝ OKRUH Softwarové inženýrství
TÉMATICKÝ OKRUH Softwarové inženýrství Číslo otázky : 24. Otázka : Implementační fáze. Postupy při specifikaci organizace softwarových komponent pomocí UML. Mapování modelů na struktury programovacího
Programování v C++ 3, 3. cvičení
Programování v C++ 3, 3. cvičení úvod do objektově orientovaného programování 1 1 Fakulta jaderná a fyzikálně inženýrská České vysoké učení technické v Praze Zimní semestr 2018/2019 Přehled Dokončení spojového
PB161 Programování v jazyce C++ Přednáška 7
PB161 Programování v jazyce C++ Přednáška 7 Statické položky tříd Základy OOP Nikola Beneš 6. listopadu 2018 PB161 přednáška 7: static, základy OOP 6. listopadu 2018 1 / 21 Klíčové slovo static Znáte z
PB161 Programování v jazyce C++ Přednáška 7
PB161 Programování v jazyce C++ Přednáška 7 Statické položky tříd Základy OOP Nikola Beneš 6. listopadu 2018 PB161 přednáška 7: static, základy OOP 6. listopadu 2018 1 / 21 Klíčové slovo static Znáte z
Novinky. Autodesk Vault helpdesk.graitec.cz,
Novinky Autodesk Vault 2018 www.graitec.cz www.cadnet.cz, helpdesk.graitec.cz, www.graitec.com Novinky Autodesk Vault 2018 PDF dokument obsahuje přehled novinek produktu Autodesk Vault 2018. Obsah: Úvod...
1. Dědičnost a polymorfismus
1. Dědičnost a polymorfismus Cíl látky Cílem této kapitoly je představit klíčové pojmy dědičnosti a polymorfismu. Předtím však je nutné se seznámit se základními pojmy zobecnění neboli generalizace. Komentář
Preprocesor. Karel Richta a kol. katedra počítačů FEL ČVUT v Praze. Karel Richta, Martin Hořeňovský, Aleš Hrabalík, 2016
Preprocesor Karel Richta a kol. katedra počítačů FEL ČVUT v Praze Karel Richta, Martin Hořeňovský, Aleš Hrabalík, 2016 Programování v C++, A7B36PJC 4/2016, Lekce 9b https://cw.fel.cvut.cz/wiki/courses/a7b36pjc/start
2015 GEOVAP, spol. s r. o. Všechna práva vyhrazena.
2015 GEOVAP, spol. s r. o. Všechna práva vyhrazena. GEOVAP, spol. s r. o. Čechovo nábřeží 1790 530 03 Pardubice Česká republika +420 466 024 618 http://www.geovap.cz V dokumentu použité názvy programových
Tento studijní blok má za cíl pokračovat v základních prvcích jazyka Java. Konkrétně bude věnována pozornost rozhraním a výjimkám.
13 Rozhraní, výjimky Studijní cíl Tento studijní blok má za cíl pokračovat v základních prvcích jazyka Java. Konkrétně bude věnována pozornost rozhraním a výjimkám. Doba nutná k nastudování 2 2,5 hodiny
Příloha 6. Palety nástrojů
Příloha 6. Palety nástrojů Palety nástrojů v IDE poskytují zkrácení pro příkazy nabídky. Příkazy jsou rozděleny do několika palet nástrojů, které mohou být nezávisle přeskupeny nebo vloženy do plovoucích
1 Uživatelská dokumentace
1 Uživatelská dokumentace Systém pro závodění aut řízených umělou inteligencí je zaměřen na závodění aut v prostředí internetu. Kromě toho umožňuje testovat jednotlivé řidiče bez nutnosti vytvářet závod
Reliance 3 design OBSAH
Reliance 3 design Obsah OBSAH 1. První kroky... 3 1.1 Úvod... 3 1.2 Založení nového projektu... 4 1.3 Tvorba projektu... 6 1.3.1 Správce stanic definice stanic, proměnných, stavových hlášení a komunikačních
11. Přehled prog. jazyků
Jiří Vokřínek, 2016 B6B36ZAL - Přednáška 11 1 Základy algoritmizace 11. Přehled prog. jazyků doc. Ing. Jiří Vokřínek, Ph.D. Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze
PB161 Programování v jazyce C++ Přednáška 9
PB161 Programování v jazyce C++ Přednáška 9 Právo friend Přetěžování operátorů Nikola Beneš 16. listopadu 2015 PB161 přednáška 9: friend, přetěžování operátorů 16. listopadu 2015 1 / 30 Reklama PB173 Tematicky
Teoretické minimum z PJV
Teoretické minimum z PJV Pozn.: následující text popisuje vlastnosti jazyka Java zjednodušeně pouze pro potřeby výuky. Třída Zavádí se v programu deklarací třídy což je část programu od klíčových slov
Softwarové komponenty a Internet
Softwarové komponenty a Internet Doc. Dr. Ing. Miroslav Beneš Katedra informatiky FEI VŠB-TU Ostrava Miroslav.Benes@vsb.cz Obsah přednášky Motivace Vývoj přístupů k tvorbě programů Definice komponenty
Pokročilé programování v jazyce C pro chemiky (C3220) Operátory new a delete, virtuální metody
Pokročilé programování v jazyce C pro chemiky (C3220) Operátory new a delete, virtuální metody Dynamická alokace paměti Jazyky C a C++ poskytují programu možnost vyžádat si část volné operační paměti pro
Abstraktní třídy, polymorfní struktury
Karel Müller, Josef Vogel (ČVUT FIT) Abstraktní třídy, polymorfní struktury BI-PA2, 2011, Přednáška 9 1/32 Abstraktní třídy, polymorfní struktury Ing. Josef Vogel, CSc Katedra softwarového inženýrství
Matematika v programovacích
Matematika v programovacích jazycích Pavla Kabelíková am.vsb.cz/kabelikova pavla.kabelikova@vsb.cz Úvodní diskuze Otázky: Jaké programovací jazyky znáte? S jakými programovacími jazyky jste již pracovali?
Vytvoření.NET komponenty (DLL) ve Visual Studiu
Jak vytvořit.net komponentu (DLL, COM Class) pro Excel? A proč? A co k tomu budeme potřebovat? Velký Visual Basic (dnes VB.NET) se rozešel s Visual Basicem pro aplikace (VBA) před cca 16 lety. A i když
VÝUKOVÝ MATERIÁL. Bratislavská 2166, 407 47 Varnsdorf, IČO: 18383874 www.vosassvdf.cz, tel. +420412372632 Číslo projektu
VÝUKOVÝ MATERIÁL Identifikační údaje školy Vyšší odborná škola a Střední škola, Varnsdorf, příspěvková organizace Bratislavská 2166, 407 47 Varnsdorf, IČO: 18383874 www.vosassvdf.cz, tel. +420412372632
DUM 06 téma: Tvorba makra pomocí VBA
DUM 06 téma: Tvorba makra pomocí VBA ze sady: 03 tematický okruh sady: Tvorba skript a maker ze šablony: 10 Algoritmizace a programování určeno pro: 4. ročník vzdělávací obor: 18-20-M/01 Informační technologie
APS mini.ed programová nadstavba pro základní vyhodnocení docházky. Příručka uživatele verze 2.2.0.6
APS mini.ed programová nadstavba pro základní vyhodnocení docházky Příručka uživatele verze 2.2.0.6 APS mini.ed Příručka uživatele Obsah Obsah... 2 Instalace a konfigurace programu... 3 Popis programu...
24-2-2 PROMĚNNÉ, KONSTANTY A DATOVÉ TYPY TEORIE DATUM VYTVOŘENÍ: 23.7.2013 KLÍČOVÁ AKTIVITA: 02 PROGRAMOVÁNÍ 2. ROČNÍK (PRG2) HODINOVÁ DOTACE: 1
24-2-2 PROMĚNNÉ, KONSTANTY A DATOVÉ TYPY TEORIE AUTOR DOKUMENTU: MGR. MARTINA SUKOVÁ DATUM VYTVOŘENÍ: 23.7.2013 KLÍČOVÁ AKTIVITA: 02 UČIVO: STUDIJNÍ OBOR: PROGRAMOVÁNÍ 2. ROČNÍK (PRG2) INFORMAČNÍ TECHNOLOGIE
1 Webový server, instalace PHP a MySQL 13
Úvod 11 1 Webový server, instalace PHP a MySQL 13 Princip funkce webové aplikace 13 PHP 14 Principy tvorby a správy webového serveru a vývojářského počítače 14 Co je nezbytné k instalaci místního vývojářského
Programovací jazyky. imperativní (procedurální) neimperativní (neprocedurální) assembler (jazyk symbolických instrukcí)
Programovací jazyky Programovací jazyky nižší assembler (jazyk symbolických instrukcí) vyšší imperativní (procedurální) Pascal, C/C++, Java, Basic, Python, php neimperativní (neprocedurální) Lisp, Prolog
Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007
Úvod do programovacích jazyků (Java) Michal Krátký 1 Katedra informatiky VŠB Technická univerzita Ostrava Úvod do programovacích jazyků (Java), 2006/2007 c 2006 Michal Krátký Úvod do programovacích jazyků
14.4.2010. Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.
Základy programování (IZAPR) Přednáška 7 Ing. Michael Bažant, Ph.D. Katedra softwarových technologií Kancelář č. 229, Náměstí Čs. legií Michael.Bazant@upce.cz Obsah přednášky 7 Parametry metod, předávání
Obsah SLEDOVÁNÍ PRÁCE... 4
Co je nového Obsah SLEDOVÁNÍ PRÁCE...... 4 Konfigurace souboru... 5 Globální konfigurace... 6 Soubory... 6 Projekty... 6 Uživatelské rozhraní... 7 Synchronizace... 7 Typ serveru... 8 Test připojení...
První kroky s METEL IEC IDE
První kroky s poskytuje programování v IEC 61131-3 jazycích, podporuje jak grafickou tak textovou podobu. Umožňuje vytvářet, upravovat a ladit IEC 61131-3 (ST, LD, IL, FBD) programy pro řídicí jednotky
Více o konstruktorech a destruktorech
Více o konstruktorech a destruktorech Více o konstruktorech a o přiřazení... inicializovat objekt lze i pomocí jiného objektu lze provést přiřazení mezi objekty v původním C nebylo možné provést přiřazení
Maturitní otázky z předmětu PROGRAMOVÁNÍ
Wichterlovo gymnázium, Ostrava-Poruba, příspěvková organizace Maturitní otázky z předmětu PROGRAMOVÁNÍ 1. Algoritmus a jeho vlastnosti algoritmus a jeho vlastnosti, formy zápisu algoritmu ověřování správnosti
Mělká a hluboká kopie
Karel Müller, Josef Vogel (ČVUT FIT) Mělká a hluboká kopie BI-PA2, 2011, Přednáška 5 1/28 Mělká a hluboká kopie Ing. Josef Vogel, CSc Katedra softwarového inženýrství Katedra teoretické informatiky, Fakulta
Windows a real-time. Windows Embedded
Windows a real-time Windows Embedded Windows pro Embedded zařízení Současnost (2008): Windows Embedded WINDOWS EMBEDDED Windows Embedded CE Windows XP Embedded Windows Embedded for Point of Service Minulé
Programování ve Windows Dynamické knihovny. Andrea Číková Martin Osovský
Programování ve Windows Dynamické knihovny Andrea Číková Martin Osovský Agenda K čemu jsou dobré? Jaký mají vztah ke spustitelným souborům a procesům? Jak se sestavují? Jak se načítají? Jak se hledají?
for (i = 0, j = 5; i < 10; i++) { // tělo cyklu }
5. Operátor čárka, - slouží k jistému určení pořadí vykonání dvou příkazů - oddělím-li čárkou dva příkazy, je jisté, že ten první bude vykonán dříve než příkaz druhý. Např.: i = 5; j = 8; - po překladu
3. Je defenzivní programování technikou skrývání implementace? Vyberte jednu z nabízených možností: Pravda Nepravda
1. Lze vždy z tzv. instanční třídy vytvořit objekt? 2. Co je nejčastější příčinou vzniku chyb? A. Specifikace B. Testování C. Návrh D. Analýza E. Kódování 3. Je defenzivní programování technikou skrývání
Pro označení disku se používají písmena velké abecedy, za nimiž následuje dvojtečka.
1 Disky, adresáře (složky) a soubory Disky Pro označení disku se používají písmena velké abecedy, za nimiž následuje dvojtečka. A:, B: C:, D:, E:, F: až Z: - označení disketových mechanik - ostatní disky
5a. Makra Visual Basic pro Microsoft Escel. Vytvořil Institut biostatistiky a analýz, Masarykova univerzita J. Kalina
5a. Makra Visual Basic pro Microsoft Escel Vytvořil Institut biostatistiky a analýz, Masarykova univerzita J. Kalina Cyklické odkazy a iterativní výpočty Zde bude stránka o cyklických odkazech a iteracích.
Úvod do jazyka C. Ing. Jan Fikejz (KST, FEI) Fakulta elektrotechniky a informatiky Katedra softwarových technologií
1 Fakulta elektrotechniky a informatiky Katedra softwarových technologií 12. října 2009 Organizace výuky Přednášky Teoretické základy dle normy jazyka C Cvičení Praktické úlohy odpřednášené látky Prostřední
Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007
Úvod do programovacích jazyků (Java) Michal Krátký Katedra informatiky VŠB Technická univerzita Ostrava Úvod do programovacích jazyků (Java), 2006/2007 c 2006 Michal Krátký Úvod do programovacích jazyků
Programování v C++ 2, 4. cvičení
Programování v C++ 2, 4. cvičení statické atributy a metody, konstruktory 1 1 Fakulta jaderná a fyzikálně inženýrská České vysoké učení technické v Praze Zimní semestr 2018/2019 Přehled Přístupová práva
Princip funkce počítače
Princip funkce počítače Princip funkce počítače prvotní úlohou počítačů bylo zrychlit provádění matematických výpočtů první počítače kopírovaly obvyklý postup manuálního provádění výpočtů pokyny pro zpracování
RMI - Distribuované objekty v Javě
Vysoká škola báňská - Technická univerzita Ostrava 30. března 2009 Osnova Co je to RMI? 1 Co je to RMI? 2 Vnější pohled Vrstvy RMI Stub & Skeletons Layer Remote Reference Layer Transport Layer Pojemnování
2 PŘÍKLAD IMPORTU ZATÍŽENÍ Z XML
ROZHRANÍ ESA XML Ing. Richard Vondráček SCIA CZ, s. r. o., Thákurova 3, 160 00 Praha 6 www.scia.cz 1 OTEVŘENÝ FORMÁT Jednou z mnoha užitečných vlastností programu ESA PT je podpora otevřeného rozhraní
PHP framework Nette. Kapitola 1. 1.1 Úvod. 1.2 Architektura Nette
Kapitola 1 PHP framework Nette 1.1 Úvod Zkratka PHP (z anglického PHP: Hypertext Preprocessor) označuje populární skriptovací jazyk primárně navržený pro vývoj webových aplikací. Jeho oblíbenost vyplývá
OPS Paralelní systémy, seznam pojmů, klasifikace
Moorův zákon (polovina 60. let) : Výpočetní výkon a počet tranzistorů na jeden CPU chip integrovaného obvodu mikroprocesoru se každý jeden až dva roky zdvojnásobí; cena se zmenší na polovinu. Paralelismus
EPLAN Electric P8 2.7 s databázemi na SQL serveru
EPLAN Electric P8 2.7 s databázemi na SQL serveru EPLAN Electric P8 2.7 k dispozici pouze ve verzi 64bit. EPLAN Electric P8 využívá k ukládání některých dat databáze. Artikly, překladový slovník 1 ) a
INSTALACE SOFTWARE PROID+ NA MS WINDOWS
INSTALACE SOFTWARE PROID+ NA MS WINDOWS Pro správnou funkčnost ProID+ je třeba na daný počítač instalovat ovládací software ProID+. Instalace ovládacího software ProID+ se provádí pomocí instalačního balíčku.
4a. Makra Visual Basic pro Microsoft Excel Cyklické odkazy a iterace Makra funkce a metody
4a. Makra Visual Basic pro Microsoft Excel Cyklické odkazy a iterace Makra funkce a metody Vytvořil Institut biostatistiky a analýz, Masarykova univerzita J. Kalina Cyklické odkazy a iterativní výpočty
VÝUKOVÝ MATERIÁL. Bratislavská 2166, Varnsdorf, IČO: tel Číslo projektu
VÝUKOVÝ MATERIÁL Identifikační údaje školy Vyšší odborná škola a Střední škola, Varnsdorf, příspěvková organizace Bratislavská 2166, 407 47 Varnsdorf, IČO: 18383874 www.vosassvdf.cz, tel. +420412372632
DSL manuál. Ing. Jan Hranáč. 27. října 2010. V této kapitole je stručný průvodce k tvorbě v systému DrdSim a (v
DSL manuál Ing. Jan Hranáč 27. října 2010 V této kapitole je stručný průvodce k tvorbě v systému DrdSim a (v současné době krátký) seznam vestavěných funkcí systému. 1 Vytvoření nového dobrodružství Nejprve
Profilová část maturitní zkoušky 2017/2018
Střední průmyslová škola, Přerov, Havlíčkova 2 751 52 Přerov Profilová část maturitní zkoušky 2017/2018 TEMATICKÉ OKRUHY A HODNOTÍCÍ KRITÉRIA Studijní obor: 78-42-M/01 Technické lyceum Předmět: TECHNIKA
Instalace a konfigurace web serveru. WA1 Martin Klíma
Instalace a konfigurace web serveru WA1 Martin Klíma Instalace a konfigurace Apache 1. Instalace stáhnout z http://httpd.apache.org/ nebo nějaký balíček předkonfigurovaného apache, např. WinLamp http://sourceforge.net/projects/winlamp/
Podpora skriptování v Audacity
Specifikace softwarového díla & Časový plán implementace pro Podpora skriptování v Audacity Audacity je oblíběný editor zvuku, který ovšem v současné době postrádá možnost automatizovaného vykonávání skriptů.
Programování v C++ 1, 6. cvičení
Programování v C++ 1, 6. cvičení dědičnost, polymorfismus 1 1 Fakulta jaderná a fyzikálně inženýrská České vysoké učení technické v Praze Zimní semestr 2018/2019 Přehled 1 2 3 Shrnutí minule procvičené
Systém adresace paměti
Systém adresace paměti Základní pojmy Adresa fyzická - adresa, která je přenesena na adresní sběrnici a fyzicky adresuje hlavní paměť logická - adresa, kterou má k dispozici proces k adresaci přiděleného
TŘÍDY POKRAČOVÁNÍ. Události pokračování. Příklad. public delegate void ZmenaSouradnicEventHandler (object sender, EventArgs e);
TŘÍDY POKRAČOVÁNÍ Události pokračování public delegate void ZmenaSouradnicEventHandler (object sender, EventArgs e); class Bod private int x; private int y; public event ZmenaSouradnicEventHandler ZmenaSouradnic;
7. přednáška - třídy, objekty třídy objekty atributy tříd metody tříd
7. přednáška - třídy, objekty třídy objekty atributy tříd metody tříd Algoritmizace (Y36ALG), Šumperk - 7. přednáška 1 Třída jako zdroj funkcionality Třída v jazyku Java je programová jednotka tvořená
Základy jazyka C# Obsah přednášky. Architektura.NET Historie Vlastnosti jazyka C# Datové typy Příkazy Prostory jmen Třídy, rozhraní
Základy jazyka C# doc. Ing. Miroslav Beneš, Ph.D. katedra informatiky FEI VŠB-TUO A-1007 / 597 324 213 http://www.cs.vsb.cz/benes Miroslav.Benes@vsb.cz Obsah přednášky Architektura.NET Historie Vlastnosti
Semestrální práce 2 znakový strom
Semestrální práce 2 znakový strom Ondřej Petržilka Datový model BlockFileRecord Bázová abstraktní třída pro záznam ukládaný do blokového souboru RhymeRecord Konkrétní třída záznamu ukládaného do blokového
Čtvrtek 3. listopadu. Makra v Excelu. Obecná definice makra: Spouštění makra: Druhy maker, způsoby tvorby a jejich ukládání
Čtvrtek 3. listopadu Makra v Excelu Obecná definice makra: Podle definice je makro strukturovanou definicí jedné nebo několika akcí, které chceme, aby MS Excel vykonal jako odezvu na nějakou námi definovanou
Nápověda k aplikaci EA Script Engine
Nápověda k aplikaci EA Script Engine Object Consulting s.r.o. 2006 Obsah Nápověda k aplikaci EA Script Engine...1 1. Co je EA Script Engine...2 2. Důležité upozornění pro uživatele aplikace EA Script Engine...3
Program a životní cyklus programu
Program a životní cyklus programu Program algoritmus zapsaný formálně, srozumitelně pro počítač program se skládá z elementárních kroků Elementární kroky mohou být: instrukce operačního kódu počítače příkazy
III/2 Inovace a zkvalitnění výuky prostřednictvím ICT
Číslo a název šablony Číslo didaktického materiálu Druh didaktického materiálu Autor Jazyk Téma sady didaktických materiálů Téma didaktického materiálu Vyučovací předmět Cílová skupina (ročník) Úroveň
Průvodce instalací modulu Offline VetShop verze 3.4
Průvodce instalací modulu Offline VetShop verze 3.4 Úvod k instalaci Tato instalační příručka je určena uživatelům objednávkového modulu Offline VetShop verze 3.4. Obsah 1. Instalace modulu Offline VetShop...
Novinky. Autodesk Vault helpdesk.graitec.cz,
Novinky Autodesk Vault 2017 www.graitec.cz www.cadnet.cz, helpdesk.graitec.cz, www.graitec.com Novinky Autodesk Vault 2017 PDF dokument obsahuje přehled novinek produktu Autodesk Vault 2017. Obsah: 1.
Úvod Třídy Rozhraní Pole Konec. Programování v C# Hodnotové datové typy, řídící struktury. Petr Vaněček 1 / 39
Programování v C# Hodnotové datové typy, řídící struktury Petr Vaněček 1 / 39 Obsah přednášky Referenční datové typy datové položky metody přístupové metody accessory, indexery Rozhraní Pole 2 / 39 Třídy