Міністерство освіти і науки України
Національний університет “Львівська політехніка”
Кафедра автоматизованих систем управління
Лабораторна робота
На тему
Com-об`єкти
Component Object Model
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 був розроблений в 1993 році корпорацією Майкрософт як основа для розвитку технології OLE. Технологія OLE 1.0 вже дозволяла створювати так звані «складені документи»: наприклад, в пакеті Microsoft Office ця технологія дозволяла включати діаграми Microsoft Excel в документи Microsoft Word). Стандарт COM мав уніфікувати процес створення, впровадження і скріплення таких упроваджуваних об'єктів, а також стандартизувати розробку застосунків, що використовують упроваджувані об'єкти.
Плутанина в назвах
В 1996 році майкрософту спробувала перейменувати технологію OLE в ActiveX, але це вдалося лише частково. Наприклад, технологія OLE дозволяла створювати так звані елементи управління OLE (англ. OLE Controls, або OCX) — повторно використовувані елементи призначеного для інтерфейсу користувача, які були побудовані на стандарті COM. Ці елементи управління OLE були перейменовані в елементи управління ActiveX (англ. ActiveX controls), хоча розширення файлів «.ocx» за ними залишилося. Потім Майкрософт став активно просувати ActiveX в Інтернет, включивши підтримку елементів ActiveX в свій популярний браузер Internet Explorer. В результаті назва OLE залишилася тільки за технологією складених документів і локальних упроваджуваних об'єктів. А мережеві OLE-об'єкти стали називати по-новому — ActiveX.
Деяка плутанина між поняттями OLE і ActiveX зберігається досі, але мова йде про ті самі COM-технології. Причому, іноді навіть плутають поняття OLE і COM. Так, упроваджувані OLE-об'єкти іноді називають COM-об'єктами, а OLE-контейнери COM-контейнерами, тощо.
Принципи роботи COM
Основним поняттям, яким оперує технологія COM, є COM-компонент. Програми, побудовані на технології COM, фактично не є автономними програмами, а є набором COM-компонентів, що взаємодіють між собою. Кожен компонент має унікальний ідентифікатор (GUID) і може одночасно використовуватися багатьма програмами. Компонент взаємодіє з іншими програмами через COM-інтерфейси — набори абстрактних функцій і властивостей. Кожен COM-компонент має, як мінімум, підтримувати стандартний інтерфейс «IUnknown», який надає базові засоби для роботи з компонентом.
Windows API надає базові функції, що дозволяють використовувати COM-компоненти. Бібліотеки MFC і, особливо, ATL/WTL надають набагато гнучкіші і зручніші засоби для роботи з COM. Бібліотека ATL від Майкрософт досі лишається найпопулярнішим засобом створення COM-компонентів. Але, часто, COM-розробка залишається ще досить складною справою, програмістам доводиться вручну виконувати багато рутинних завдань, пов'язаних з COM (особливо це помітно у разі розробки на C++). Згодом (у технологіях COM+ і особливо .NET) Майкрософт спробував спростити завдання розробки COM-компонентів.
Розвиток COM
DCOM
Випущена в 1996 році технологія DCOM (англ. Distributed COM — розподілена COM) заснована на технології DCE/RPC (різновиди RPC) і є розвитком COM. DCOM дозволяє COM-компонентам взаємодіяти один з одним по мережі. Головним конкурентом DCOM є інша відома розподілена технологія — CORBA.
COM+
У складі Windows 2000 була випущена технологія COM+, яка розширювала можливості розробників COM-компонентів, надаючи їм деякі готові послуги, наприклад:
покращену підтримку нитей;
доступ до контексту, в якому виконується компонент (наприклад, компоненти, використані в ASP, можуть з цією можливістю дістати доступ до внутрішніх об'єктів тієї сторінки, на якій вони виконуються).
COM+ об'єднує компоненти в так звані застосунки COM+, що спрощує адміністрування і обслуговування компонентів. Безпека і продуктивність — основні напрями удосконалень COM+. Деякі ідеї, закладені в основу COM+, були також реалізовані в .NET.
.NET і майбутнє COM
В 2002 році була офіційно випущена платформа Microsoft .NET, яка на сьогоднішній день оголошена Майкрософтом рекомендованою основою для створення застосувань і компонентів під Windows. З цієї причини в .NET включені і засоби, що дозволяють звертатися до компонентів COM із застосувань .NET, і навпаки. За словами представників Майкрософту, COM (точніше, COM+) і .NET є відмінно взаємно доповнюючими технологіями. Також було заявлено, що Windows Vista побудована з використанням технологій .NET і COM+.
.386
.model flat,stdcall
option casemap:none
DlgProc proto :DWORD,:DWORD,:DWORD,:DWORD
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\advapi32.inc
include \masm32\include\ole32.inc
include \masm32\include\oleaut32.inc
include \masm32\include\comctl32.inc
include \masm32\include\shell32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\ole32.lib
includelib \masm32\lib\oleaut32.lib
includelib \masm32\lib\advapi32.lib
includelib \masm32\lib\comctl32.lib
includelib \masm32\lib\shell32.lib
.data
idx DWORD 0
cnt DWORD 0
mjver DWORD 0
DlgName db "MyDialog",0
App db "TypeLibs",0
ms1 db "No help file",0
ms5 db "There is no help for this component",0
cl1 db "Component",0
cl2 db "TypeLib",0
SubKey1 db "CLSID",0
s db "\",0
CRLF db 13,10,0
findbuf db "Typelib",0
cmd db "open",0
Err1 db "RegOpenKeyEx failed",0
Err2 db "RegEnumKeyEx failed",0
Err3 db "RegQueryValueEx failed",0
Err4 db "CLSIDFromString failed",0
Err5 db "LoadRegTypeLib failed",0
Err6 db "GetDocumentation failed",0
Err7 db "No Type Library installed",0
fmt db "Error loading help file:",13,10,"%s",0
.data?
hInstance HINSTANCE ?
hList DWORD ?
HKey DWORD ?
HKey2 DWORD ?
HKey3 DWORD ?
sbksz DWORD ?
bsz DWORD ?
pTlib DWORD ?
HelpFile DWORD ?
CompName DWORD ?
DocString DWORD ?
buf db 512 dup(?)
wbuf db 512 dup(?)
SubKey2 db 256 dup(?)
SubKey3 db 256 dup(?)
SubKeyBuf db 256 dup(?)
TlibGuid db 16 dup(?)
clmn LVCOLUMN <>
item LVITEM <>
sbitm LVITEM <>
.const
IDC_LIST1 equ 1000
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke InitCommonControls
invoke DialogBoxParam, hInstance, ADDR DlgName,NULL, addr DlgProc, NULL
invoke ExitProcess,eax
DlgProc proc USES esi edi ebx,hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_INITDIALOG
invoke GetDlgItem,hWnd,IDC_LIST1
mov hList,eax
mov clmn.imask,LVCF_WIDTH or LVCF_TEXT or LVCF_SUBITEM
mov clmn.lx,225
mov clmn.pszText,OFFSET cl1
mov clmn.iSubItem,0
invoke SendMessage,hList,LVM_INSERTCOLUMN,0,ADDR clmn
mov clmn.lx,250
mov clmn.pszText,OFFSET cl2
mov clmn.iSubItem,1
invoke SendMessage,hList,LVM_INSERTCOLUMN,1,ADDR clmn
mov item.imask,LVIF_TEXT
mov item.pszText,OFFSET buf
invoke CoInitialize,0
invoke RegOpenKeyEx,HKEY_CLASSES_ROOT,ADDR SubKey1,0,KEY_ALL_ACCESS,ADDR HKey
.if eax==ERROR_SUCCESS
EnumLoop:
lea esi,buf
mov sbksz,255
invoke RegEnumKeyEx,HKey,idx,ADDR SubKeyBuf,ADDR sbksz,0,0,0,0
.if eax==ERROR_NO_MORE_ITEMS
jmp OutLoop
.elseif eax!=ERROR_SUCCESS
invoke MessageBox,0,ADDR Err2,ADDR App,MB_OK OR MB_ICONERROR
jmp OutLoop
.endif
invoke lstrcpy,ADDR SubKey2,ADDR SubKey1
invoke lstrcpy,ADDR SubKey3,ADDR SubKey1
invoke lstrcat,ADDR SubKey2,ADDR s
invoke lstrcat,ADDR SubKey3,ADDR s
invoke lstrcat,ADDR SubKey2,ADDR SubKeyBuf
invoke lstrcat,ADDR SubKey3,ADDR SubKeyBuf
invoke lstrcat,ADDR SubKey3,ADDR s
invoke lstrcat,ADDR SubKey3,ADDR findbuf
invoke RegOpenKeyEx,HKEY_CLASSES_ROOT,ADDR SubKey3,0,KEY_ALL_ACCESS,ADDR HKey3
.if eax==ERROR_SUCCESS
invoke RegOpenKeyEx,HKEY_CLASSES_ROOT,ADDR SubKey2,0,KEY_ALL_ACCESS,ADDR HKey2
.if eax==ERROR_SUCCESS
mov bsz,255
invoke RegQueryValueEx,HKey2,0,0,0,ADDR buf,ADDR bsz
mov eax,cnt
mov item.iItem,eax
mov item.iSubItem,0
invoke SendMessage,hList,LVM_INSERTITEM,0,ADDR item
mov bsz,255
invoke RegQueryValueEx,HKey3,0,0,0,ADDR buf,ADDR bsz
.if eax==ERROR_SUCCESS
mov item.iSubItem,1
invoke SendMessage,hList,LVM_SETITEM,0,ADDR item
.endif
invoke RegCloseKey,HKey2
inc cnt
.endif ;RegOpenKeyEx (SubKey2)
invoke RegCloseKey,HKey3
.endif ;RegOpenKeyEx (SubKey3)
inc idx
jmp EnumLoop
OutLoop:
invoke RegCloseKey,HKey
.else
invoke MessageBox,0,ADDR Err1,ADDR App,MB_OK OR MB_ICONERROR
jmp Ex_0
.endif ;RegOpenKeyEx ()
.ELSEIF uMsg==WM_NOTIFY
mov ebx,lParam
assume ebx:ptr NMHDR
.if [ebx].code==NM_DBLCLK
call FindHelp
.endif
assume ebx:nothing
.ELSEIF uMsg==WM_CLOSE
Ex_0:
invoke CoUninitialize
invoke EndDialog,hWnd,0
.ELSE
mov eax,FALSE
ret
.ENDIF ;uMsg
mov eax,TRUE
ret
DlgProc endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; FindHelp: handler of dblclks in listview control.
;; In: NMLISTVIEW structure ptr in ebx (pszText field containing
;; choosen TypeLib's GUID in ASCII (string) form)
;; Function enumerates version subkeys under abovementioned GUID,
;; chooses the biggest one, loads TypeLib with this maj.version using
;; LoadRegTypeLib and getting ITypeLib pointer, then calls member fn.
;; ITypeLib->GetDocumentation and shows result in MessageBox,
;; if no help file is present. If there is help file, it is loaded
;; and displayed.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FindHelp proc
assume ebx:ptr NMLISTVIEW
mov eax,[ebx].iItem
mov item.iItem,eax
.if eax==-1
ret
.endif
assume ebx:nothing
mov item.imask,LVIF_TEXT
mov item.iSubItem,1
mov item.pszText,OFFSET buf
mov item.cchTextMax,255
invoke SendMessage,hList,LVM_GETITEM,0,ADDR item
;find the greatest major version of TypeLib present
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
invoke lstrcpy,ADDR SubKey2,ADDR cl2
invoke lstrcat,ADDR SubKey2,ADDR s
invoke lstrcat,ADDR SubKey2,ADDR buf
;SubKey2 = HKCR\TypeLib\{Type-Lib-GUID}
invoke RegOpenKeyEx,HKEY_CLASSES_ROOT,ADDR SubKey2,0,KEY_ALL_ACCESS,ADDR HKey
.if eax==ERROR_SUCCESS
mov idx,0
mov mjver,0
TlibLoop:
mov sbksz,255
;subkeys in 'HKCR\TypeLib\{Type-Lib-GUID}' are
;in the form majversion.minversion
invoke RegEnumKeyEx,HKey,idx,ADDR SubKeyBuf,ADDR sbksz,0,0,0,0
.if eax==ERROR_SUCCESS
xor eax,eax
mov al,SubKeyBuf ;first char of subkey (i.e. majversion)
sub eax,30h ;char->value
cmp mjver,eax
jge Tlib1 ;choose the greater value of version
mov mjver,eax
Tlib1:
inc idx
jmp TlibLoop
.endif ;RegEnumKeyEx
invoke RegCloseKey,HKey
;Load Type Library with found major version
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
invoke MultiByteToWideChar,CP_ACP,0,ADDR buf,-1,ADDR wbuf,510
invoke CLSIDFromString,ADDR wbuf,ADDR TlibGuid
.if eax==NOERROR
invoke LoadRegTypeLib,ADDR TlibGuid,mjver,0,0,ADDR pTlib
.if eax==S_OK ;we got valid ITypeLib pointer (pTlib)
;call member function GetDocumentation (offset=24h)
push OFFSET HelpFile
push 0 ;pBstrHelpCtx=NULL
push OFFSET DocString
push OFFSET CompName
push -1 ;index (-1='Entire library')
mov eax,pTlib
push eax ;this ptr
mov eax,[eax] ;eax=pVtbl
call dword ptr [eax+24h] ;GetDocumentation
.if eax==S_OK
;we got help file name ptr (in HelpFile)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.if HelpFile==0 ;no help file, construct general info only
invoke WideCharToMultiByte,CP_ACP,0,CompName,-1,ADDR SubKeyBuf,255,0,0
invoke lstrcpy,ADDR wbuf,ADDR SubKeyBuf
invoke lstrcat,ADDR wbuf,ADDR CRLF
invoke WideCharToMultiByte,CP_ACP,0,DocString,-1,ADDR SubKeyBuf,255,0,0
invoke lstrcat,ADDR wbuf,ADDR SubKeyBuf
invoke lstrcat,ADDR wbuf,ADDR CRLF
invoke lstrcat,ADDR wbuf,ADDR ms1
invoke MessageBox,0,ADDR wbuf,ADDR App,MB_OK or MB_ICONINFORMATION
.else ;load and show help file
invoke WideCharToMultiByte,CP_ACP,0,HelpFile,-1,ADDR buf,255,0,0
invoke ShellExecute,0,ADDR cmd,ADDR buf,0,0,SW_SHOW
.if eax<33 ;ShellExecute error
invoke wsprintf,ADDR wbuf,ADDR fmt,ADDR buf
invoke MessageBox,0,ADDR wbuf,ADDR App,MB_OK or MB_ICONERROR
.endif
.endif ;HelpFile==0
invoke SysFreeString,HelpFile ;clean up
invoke SysFreeString,CompName
invoke SysFreeString,DocString
.else
invoke MessageBox,0,ADDr Err6,ADDR App,MB_OK or MB_ICONERROR
.endif ;GetDocumentation
mov eax,pTlib
push eax ;this
mov eax,[eax] ;eax==pVtbl
call dword ptr [eax+8] ;Function #3 (Release)
.else ;loading TypeLibrary failed
invoke MessageBox,0,ADDR Err5,ADDR App,MB_OK or MB_ICONERROR
.endif ;LoadRegTypeLib==S_OK
.else
invoke MessageBox,0,ADDR Err4,ADDR App,MB_OK or MB_ICONERROR
.endif ;CLSIDFromString==NOERROR
.else
invoke MessageBox,0,ADDR Err7,ADDR App,MB_OK or MB_ICONERROR
ret
.endif ;RegOpenKeyEx==ERROR_SUCCESS
ret
FindHelp endp
end start
Висновок:На цій лабораторній роботі я дізнався що таке сом-об’єкти, навчився практично їх використовувати.