Міністерство освіти і науки України
Національний університет «Львівська політехніка»
Кафедра АСУ
Лабораторна робота №7
Тема:Використання com-об’єктів
Написав: ст. гр.. КН-22
Прийняв: Скрибайло-Леськів Д.Ю
Львів 2011
Лабораторна робота №7
Теоретичні основи
COM (Component Object Model) — платформа компонентно-орієнтованого програмування розроблена в 1993 році компанією Microsoft; дозволяє використання міжпроцесної взаємодії (inter-process communication) та динамічного створення об'єктів у будь-якій мові програмування, що підтримує технологію. Використовується переважно у ОС Віндовз, хоча була реалізована на декількох платформах.
Основним поняттям, яким оперує технологія COM, є COM-компонент. Програми, побудовані на технології COM фактично не є автономними програмами, а представляють собою набір взаємодіючих між собою COM-компонентів. Кожен компонент має унікальний ідентифікатор GUID і може одночасно використовуватися багатьма програмами. Компоненти взаємодіють між собою через COM-інтерфейси — набори абстрактних функцій і властивостей. Кожен COM-компонент повинен підтримувати стандартний інтерфейс «IUnknown», який об'єднує базові засоби для роботи з компонентом.
Windows API об'єднує базові функції, що дозволяють використовувати COM-компоненти. Бібліотека MFC і, особливо, ATL/WTL забезпечують більш гнучкі і зручні засоби для роботи з COM.
Основним поняттям, яким оперує технологія COM, є COM-компонент. Програми, побудовані на технології COM, фактично не є автономними програмами, а є набором COM-компонентів, що взаємодіють між собою. Кожен компонент має унікальний ідентифікатор (GUID) і може одночасно використовуватися багатьма програмами. Компонент взаємодіє з іншими програмами через COM-інтерфейси — набори абстрактних функцій і властивостей. Кожен COM-компонент має, як мінімум, підтримувати стандартний інтерфейс «IUnknown», який надає базові засоби для роботи з компонентом.
Windows API надає базові функції, що дозволяють використовувати COM-компоненти. Бібліотеки MFC і, особливо, ATL/WTL надають набагато гнучкіші і зручніші засоби для роботи з COM. Бібліотека ATL від Майкрософт досі лишається найпопулярнішим засобом створення COM-компонентів. Але, часто, COM-розробка залишається ще досить складною справою, програмістам доводиться вручну виконувати багато рутинних завдань, пов'язаних з COM (особливо це помітно у разі розробки на C++). Згодом (у технологіях COM+ і особливо .NET) Майкрософт спробував спростити завдання розробки COM-компонентів.
Суттю даної технології є те, що програми будуються з компонент, які складаються з об'єктів. Саме по собі ця обставина не є останньою новиною в області програмобудуванні - модульна архітектура і об'єктно-орієнтований підхід до побудови програм давно є визнаними стандартами de facto. Новиною є те, що є цими компонентами та об'єктами - ними є безпосередньо виконуваний двійковий код. Так-так, не "включаються вихідні тексти" компільовані спільно з проектом, не "бібліотеки стандартних програм", що приєднуються лінкером, а безпосередньо виконуючі файли, які ніяк не треба "зв'язувати" зі своїм проектом - їх достатньо зареєструвати в операційній системі і вони будуть доступні будь-якій програма яка виконується на даній машині. Тобто їх використання у своїй програмі проводиться "без використання операцій складання модуля".
Така технологія називається "динамічна завантаження", вона давно відома і її переваги очевидні. А модулі, які дозволяють завантажувати себе таким чином, називаються DLL. І у системі, що іменується Microsoft Windows така технологія відома від самого її народження ... А DLL і є той самий "двійковий виконуючий модуль", який може бути приєднаний до програми лише на стадії її виконання.
Виходить, якщо весь проект розподілити за кількома динамічним бібліотекам, то вийдуть "виконавчі компоненти"?
Не зовсім ... Дійсно, найважливіша ознака "компонентного" вже з'явиться – виконуючу
програму можна буде збирати з окремих частин без операцій складання модуля. Але ось DLL - не компонента, DLL є, якщо можна так висловитися, тільки "місце проживання компонент" використовуються в програмі. Адже з програми-то викликаються цілком конкретні процедури і функції, які тільки розташовані в DLL. Крім того, виклики процедур "зі свого модуля" і "з DLL" - не однакові дії. Виклик процедури, яка розташовується всередині "свого" модуля вимагає знання тільки імені цієї процедури, а якщо процедура розташовується в DLL, то потрібно знати ще й ім'я самої бібліотеки. Модель самі COM дозволяє цього "не знати", тобто виклик об'єктів COM зі своєї програми здійснюється без знання того, де вони розташовані. Достатньо знати ім'я об'єкта.
Інша відмінність COM, вже від звичних об'єктів в стилі об'єктно-орієнтованого програмування (ООП), полягає в тому, що об'єкти ООП відомі тільки компілятору. Це - абстракції, в яких мислить програміст і які компілятор перетворює на виконавчі структури "дані + код". Об'єкти ООП існуючі в різних одиницях компіляції і, тим більше, поміщені в різні виконавчі модулі, нічого не можуть один про одного "знати" просто тому, що їх там немає і ніколи не було. Не випадково заголовні файли, що містять описи всіх об'єктів проекту, подаються на вхід саме компілятора - потім вони вже нікому не потрібні. Об'єкти ж COM - дійсно існують в двійковому вигляді як об'єкти. І в такій якості відомі всім, хто відчуває в них потребу.
Словом, якщо обмежити обсяг цього есе, тільки відповіддю на питання "в чому суть?", То технологія COM є технологія, яка переносить всі переваги ООП, доступні програмісту на рівні початкового тексту, на двійковий рівень. Якщо у вихідному тексті програміст вільний використовувати "ті" об'єкти і не використовувати "ці", але втрачає усілякий контроль над тим, що він робив, як тільки вихідний текст був скомпільований, то при використанні COM ці можливості зберігаються протягом усього життєвого циклу програми. Додатково до цього додаються можливості поділу проекту на окремі, повторноіспользуемие, і виконавчі компоненти. Тобто, якщо в результаті непосильної праці у програміста виходить щось хороше і потрібне, хоча б частково, комусь іншому, то, оформивши це у вигляді COM-сервера, він сміливо може це поширювати, не ризикуючи щось втратити - адже контроль за вихідним текстом залишається у нього. У той же час всі користувачі цього об'єкта будуть його використовувати так само, як і свій, "рідний", об'єкт.
Формулювання завдання
Реалізувати керування Microsoft Agent 2.0 Merlin. Рух, графічні ефекти.
КОД ПРОГРАМИ
.386
.model flat, stdcall ;32 bit memory model
option casemap :none ;case sensitive
include Semen_1.inc
.code
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke InitCommonControls
invoke DialogBoxParam,hInstance,IDD_DIALOG1,NULL,addr DlgProc,NULL
invoke ExitProcess,0
;########################################################################
GetLinkInfo proc
LOCAL PPid,hProcess:DWORD
LOCAL pRemoveMem:DWORD
LOCAL readed:DWORD
invoke FindWindow,str@('ProgMan'),NULL
invoke GetWindow,eax, GW_CHILD
invoke GetWindow,eax, GW_CHILD
mov DesktopHandle,eax
invoke SendMessage,eax,LVM_GETITEMCOUNT,0,0
mov count_links,eax
invoke GetWindowThreadProcessId,DesktopHandle,addr PPid
invoke OpenProcess,PROCESS_ALL_ACCESS,0,PPid
mov hProcess,eax
invoke VirtualAllocEx,eax,0,3200,MEM_RESERVE or MEM_COMMIT,PAGE_READWRITE
mov pRemoveMem,eax
mov ecx,count_links
mov edi,eax
@@: push ecx
dec ecx
invoke SendMessage,DesktopHandle,LVM_GETITEMPOSITION,ecx,edi
add edi,sizeof POINT
pop ecx
loop @B
invoke ReadProcessMemory,hProcess,pRemoveMem,addr mas_link,3200,addr readed
invoke VirtualFreeEx,hProcess,pRemoveMem,3200,MEM_RELEASE
ret
GetLinkInfo endp
Click proc x,y:DWORD
LOCAL buf[1000]:byte
LOCAL adr:DWORD
pushad
cinvoke hAgentChar,MoveTo,hAgentChar,x,y,1,offset Ind
invoke Sleep,5000
mov ecx,offset Do_
call Go
mov ecx,offset Do_1
call Go
mov ecx,offset Do_2
call Go
invoke SetCursorPos,x,y
invoke Sleep,2000
invoke mouse_event,MOUSEEVENTF_LEFTDOWN,x,y,0,0
invoke mouse_event,MOUSEEVENTF_LEFTUP,x,y,0,0
invoke mouse_event,MOUSEEVENTF_LEFTDOWN,x,y,0,0
invoke mouse_event,MOUSEEVENTF_LEFTUP,x,y,0,0
popad
ret
Go:
invoke MultiByteToWideChar,0,0,ecx,-1,addr buf,1000
invoke SysAllocString,addr buf
mov adr,eax
cinvoke hAgentChar,Play,hAgentChar,eax,offset Ind
invoke SysFreeString,adr
retn
Click endp
Random_Clik proc
invoke nrandom,count_links
mov ecx,sizeof POINT
mul ecx
add eax,offset mas_link
assume eax: ptr POINT
invoke Click,[eax].x,[eax].y
assume eax: DWORD
ret
Random_Clik endp
DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
mov eax,uMsg
.if eax==WM_INITDIALOG
invoke CoInitialize,0
invoke CoCreateInstance,addr CLSID_AgentServer, 0, CLSCTX_SERVER, offset IID_IAgentEx, offset hAgentObject
cinvoke hAgentObject,Load,hAgentObject,VPath,0,0,0,offset IChrID,offset IReqID
cinvoke hAgentObject,GetChar,hAgentObject,IChrID,offset hAgentChar
cinvoke hAgentChar,SetLanguageID,hAgentChar,409h
cinvoke hAgentChar,Show,hAgentChar,0,offset Ind
invoke Sleep,2000
call GetLinkInfo
.elseif eax==WM_COMMAND
.if wParam == 1002
invoke SetTimer,hWin,10,500,offset Random_Clik
.elseif wParam == 1003
invoke KillTimer,hWin,10
.elseif wParam==1004
mov curent_index,0
mov eax,sizeof POINT
mul curent_index
add eax,offset mas_link
assume eax: ptr POINT
invoke Click,[eax].x,[eax].y
assume eax: DWORD
.elseif wParam ==1005
inc curent_index
mov eax,count_links
mov eax,sizeof POINT
mul curent_index
add eax,offset mas_link
assume eax: ptr POINT
invoke Click,[eax].x,[eax].y
assume eax: DWORD
dec curent_index
mov eax,count_links
.elseif wParam==1006
inc curent_index
mov eax,count_links
inc curent_index
mov eax,count_links
mov eax,sizeof POINT
mul curent_index
add eax,offset mas_link
assume eax: ptr POINT
invoke Click,[eax].x,[eax].y
assume eax: DWORD
dec curent_index
mov eax,count_links
dec curent_index
mov eax,count_links
.endif
.elseif eax==WM_CLOSE
cinvoke hAgentChar,Hide,hAgentChar,1,offset Ind
cinvoke hAgentObject,Unload,hAgentObject,IChrID
invoke CoUninitialize
invoke EndDialog,hWin,0
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
DlgProc endp
end start
include windows.inc
include kernel32.inc
include user32.inc
include Comctl32.inc
include shell32.inc
includelib kernel32.lib
includelib user32.lib
includelib Comctl32.lib
includelib shell32.lib
include ole32.inc
includelib ole32.lib
include oleaut32.inc
includelib oleaut32.lib
include masm32.inc
includelib masm32.lib
DlgProc PROTO :HWND,:UINT,:WPARAM,:LPARAM
MoveTo = 70h
Show = 64h
Hide = 68h
Load = 1ch
GetChar = 2ch
SetLanguageID = 0C4h
Play = 50h
Wait_ = 5cH
Unload = 20h
include RADbg.inc
cinvoke MACRO name,interface,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12, \
p13,p14,p15,p16,p17,p18,p19,p20,p21,p22
FOR arg,<p22,p21,p20,p19,p18,p17,p16,p15,p14,p13,\
p12,p11,p10,p9,p8,p7,p6,p5,p4,p3,p2,p1>
IFNB <arg> ;; If not blank
push arg ;; push parameter
ENDIF
ENDM
mov edx,name
mov edx,[edx]
call dword ptr [edx+interface] ;; call the procedure
ENDM
str@ macro Text:VARARG
LOCAL lbl1
LOCAL Name
jmp lbl1
Name db Text,0
lbl1:
exitm <offset Name>
endm
.const
IDD_DIALOG1 equ 101
;#########################################################################
.data
CLSID_AgentServer dd 0d45fd2fch
dw 5c6eh, 11d1h
db 9Eh,0C1h, 00h, 0C0h,4Fh,0D7h,08h,1Fh
IID_IAgentEx dd 48d12ba0h
dw 5b77h,11d1h
db 9Eh,0C1h, 00h,0C0h,4Fh,0D7h,08h,1Fh
Do_ db "DoMagic1",0
Do_1 db "DoMagic2",0
Do_2 db "Blink",0
Ind dd 0
IChrID dd 0
IReqID dd 0
VPath dd 0
curent_index dd 0
.data?
hInstance dd ?
hAgentObject dd ?
hAgentChar dd ?
mas_link POINT 400 dup(<?>)
count_links dd ?
DesktopHandle dd ?
;#########################################################################